diff --git a/docs/demos/basic.html b/docs/demos/basic.html index 7f489c3..69facd5 100644 --- a/docs/demos/basic.html +++ b/docs/demos/basic.html @@ -45,7 +45,7 @@


Credential ID: {{registrationParsed.credential.id}}

-

Public Key: {{registrationParsed.credential.publicKey.substring(0,32)}}...

+

Public Key: {{registrationParsed.credential.publicKey}}

Algorithm: {{registrationParsed.credential.algorithm}}

@@ -56,7 +56,7 @@ No

Credential ID: {{authenticationParsed.credentialId}}

-

Signature: {{authenticationParsed.signature.substring(0,32)}}...

+

Counter: {{authenticationParsed.counter}}


diff --git a/docs/demos/conditional-ui.html b/docs/demos/conditional-ui.html index b2322e7..93f4cc4 100644 --- a/docs/demos/conditional-ui.html +++ b/docs/demos/conditional-ui.html @@ -55,13 +55,13 @@


Credential ID: {{registrationParsed.credential.id}}

-

Public Key: {{registrationParsed.credential.publicKey.substring(0,32)}}...

+

Public Key: {{registrationParsed.credential.publicKey}}

Algorithm: {{registrationParsed.credential.algorithm}}

Credential ID: {{authenticationParsed.credentialId}}

-

Signature: {{authenticationParsed.signature.substring(0,32)}}...

+

Counter: {{authenticationParsed.counter}}


diff --git a/docs/demos/js/playground.js b/docs/demos/js/playground.js index 2cbfec3..8bf68f0 100644 --- a/docs/demos/js/playground.js +++ b/docs/demos/js/playground.js @@ -64,6 +64,32 @@ const app = new Vue({ isValid: null } }, + computed: { + parsedAuthData() { + const authData = this.verification.authenticatorData + if(!authData) + return null + try { + return webauthn.parsers.parseAuthenticator(authData) + } + catch(e) { + console.warn(e) + return "ERROR: failed to parse authenticator data. See console logs for more details." + } + }, + parsedClientData() { + const clientData = this.verification.clientData + if(!clientData) + return null + try { + return webauthn.parsers.parseClient(clientData) + } + catch(e) { + console.warn(e) + return "ERROR: failed to parse client data. See console logs for more details." + } + } + }, methods: { newChallenge() { return webauthn.server.randomChallenge() @@ -126,6 +152,22 @@ const app = new Vue({ }) } }, + async verifyPublicKey() { + const algorithm = this.verification.algorithm + const publicKey = this.verification.publicKey + if(!algorithm) + return window.alert('No algorithm defined!') + if(!publicKey) + return window.alert('Public key not defined!') + try { + const parsedKey = await webauthn.server.parseCryptoKey(algorithm, publicKey) + console.log(parsedKey) + return window.alert('Public key is VALID') + } catch (error) { + console.warn(error) + return window.alert('INVALID public key: see details in console logs') + } + }, async verifySignature() { try { this.verification.isValid = await webauthn.server.verifySignature(this.verification) @@ -138,12 +180,6 @@ const app = new Vue({ }) this.verification.isValid = false } - }, - parseAuthData(authData) { - return webauthn.parsers.parseAuthenticator(authData) - }, - parseClientData(clientData) { - return webauthn.parsers.parseClient(clientData) } } }) \ No newline at end of file diff --git a/docs/demos/js/webauthn.min.js b/docs/demos/js/webauthn.min.js index e389f4a..4581e5f 100644 --- a/docs/demos/js/webauthn.min.js +++ b/docs/demos/js/webauthn.min.js @@ -1,3 +1,3 @@ -/*passwordless-id/webauthn@2.0.5*/ -var U=Object.defineProperty;var y=(e,t)=>{for(var a in t)U(e,a,{get:t[a],enumerable:!0})};var w={};y(w,{authenticate:()=>k,isAutocompleteAvailable:()=>B,isAvailable:()=>x,isLocalAuthenticator:()=>v,register:()=>V});var u={};y(u,{bufferToHex:()=>C,concatenateBuffers:()=>O,isBase64url:()=>g,parseBase64url:()=>o,parseBuffer:()=>K,sha256:()=>A,toBase64url:()=>n,toBuffer:()=>f});function f(e){return Uint8Array.from(e,t=>t.charCodeAt(0)).buffer}function K(e){return String.fromCharCode(...new Uint8Array(e))}function g(e){return e.match(/^[a-zA-Z0-9\-_]+=*$/)!==null}function n(e){return btoa(K(e)).replaceAll("+","-").replaceAll("/","_")}function o(e){return e=e.replaceAll("-","+").replaceAll("_","/"),f(atob(e))}async function A(e){return await crypto.subtle.digest("SHA-256",e)}function C(e){return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}function O(e,t){var a=new Uint8Array(e.byteLength+t.byteLength);return a.set(new Uint8Array(e),0),a.set(new Uint8Array(t),e.byteLength),a}function x(){return!!window.PublicKeyCredential}async function v(){return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}function H(e){if(!(!e||e.length===0))return e.includes("client-device")?e.includes("security-key")||e.includes("hybrid")?void 0:"platform":"cross-platform"}var s=null;async function V(e){if(!e.challenge)throw new Error('"challenge" required');if(!e.user)throw new Error('"user" required');if(!g(e.challenge))throw new Error("Provided challenge is not properly encoded in Base64url");let t=typeof e.user=="string"?{name:e.user}:e.user;t.id||(t.id=crypto.randomUUID());let a={challenge:o(e.challenge),rp:{id:e.domain??window.location.hostname,name:e.domain??window.location.hostname},user:{id:f(t.id),name:t.name,displayName:t.displayName??t.name},hints:e.hints,pubKeyCredParams:[{alg:-7,type:"public-key"},{alg:-257,type:"public-key"}],timeout:e.timeout,authenticatorSelection:{userVerification:e.userVerification,authenticatorAttachment:H(e.hints),residentKey:e.discoverable??"preferred",requireResidentKey:e.discoverable==="required"},attestation:"direct"};console.debug(a),s?.abort("Cancel ongoing authentication"),s=new AbortController;let r=await navigator.credentials.create({publicKey:a,signal:s?.signal}),i=r.response;if(s=null,console.debug(r),r.type!="public-key")throw"Unexpected credential type!";let c=i.getPublicKey();if(!c)throw"Non-compliant browser or authenticator!";return{type:r.type,id:r.id,rawId:n(r.rawId),authenticatorAttachment:r.authenticatorAttachment,clientExtensionResults:r.getClientExtensionResults(),response:{attestationObject:n(i.attestationObject),authenticatorData:n(i.getAuthenticatorData()),clientDataJSON:n(i.clientDataJSON),publicKey:n(c),publicKeyAlgorithm:i.getPublicKeyAlgorithm(),transports:i.getTransports()},user:t}}async function B(){return PublicKeyCredential.isConditionalMediationAvailable&&PublicKeyCredential.isConditionalMediationAvailable()}async function k(e){if(!g(e.challenge))throw new Error("Provided challenge is not properly encoded in Base64url");if(e.autocomplete&&!await B())throw new Error("PAsskeys autocomplete with conditional mediation is not available in this browser.");let t={challenge:o(e.challenge),rpId:e.domain??window.location.hostname,allowCredentials:e.allowCredentials?.map(L),hints:e.hints,userVerification:e.userVerification,timeout:e.timeout};console.debug(t),e.autocomplete&&(s?.abort("Cancel ongoing authentication"),s=new AbortController);let a=await navigator.credentials.get({publicKey:t,mediation:e.autocomplete?"conditional":void 0,signal:s?.signal});if(a.type!="public-key")throw"Unexpected credential type!";s=null,console.debug(a);let r=a.response;return{clientExtensionResults:a.getClientExtensionResults(),id:a.id,rawId:n(a.rawId),type:a.type,authenticatorAttachment:a.authenticatorAttachment,response:{authenticatorData:n(r.authenticatorData),clientDataJSON:n(r.clientDataJSON),signature:n(r.signature),userHandle:r.userHandle?n(r.userHandle):void 0}}}function L(e){return typeof e=="string"?{id:o(e),type:"public-key"}:{id:o(e.id),type:"public-key",transports:e.transports}}var F={};y(F,{randomChallenge:()=>z,verifyAuthentication:()=>X,verifyRegistration:()=>j,verifySignature:()=>T});var h={};y(h,{getAlgoName:()=>E,parseAuthentication:()=>G,parseAuthenticator:()=>b,parseClient:()=>S,parseRegistration:()=>$,toAuthenticationInfo:()=>I,toRegistrationInfo:()=>N});var p={"00000000-0000-0000-0000-000000000000":"Unknown authenticator","0076631b-d4a0-427f-5773-0ec71c9e0279":"HYPR FIDO2 Authenticator","07a9f89c-6407-4594-9d56-621d5f1e358b":"NXP Semiconductros FIDO2 Conformance Testing CTAP2 Authenticator","08987058-cadc-4b81-b6e1-30de50dcbe96":"Windows Hello","092277e5-8437-46b5-b911-ea64b294acb7":"Taglio CTAP2.1 CS","09591fc6-9811-48f7-8f57-b9f23df6413f":"Pone Biometrics OFFPAD Authenticator","0acf3011-bc60-f375-fb53-6f05f43154e0":"Nymi FIDO2 Authenticator","0bb43545-fd2c-4185-87dd-feb0b2916ace":"Security Key NFC by Yubico - Enterprise Edition","0d9b2e56-566b-c393-2940-f821b7f15d6d":"Excelsecu eSecu FIDO2 Pro Security Key","0ea242b4-43c4-4a1b-8b17-dd6d0b6baec6":"Keeper","1105e4ed-af1d-02ff-ffff-ffffffffffff":"Egomet FIDO2 Authenticator for Android","12ded745-4bed-47d4-abaa-e713f51d6393":"Feitian AllinOne FIDO2 Authenticator","149a2021-8ef6-4133-96b8-81f8d5b7f1f5":"Security Key by Yubico with NFC","17290f1e-c212-34d0-1423-365d729f09d9":"Thales PIN iOS SDK","175cd298-83d2-4a26-b637-313c07a6434e":"Chunghwa Telecom FIDO2 Smart Card Authenticator","19083c3d-8383-4b18-bc03-8f1c9ab2fd1b":"YubiKey 5 Series","1c086528-58d5-f211-823c-356786e36140":"Atos CardOS FIDO2","20f0be98-9af9-986a-4b42-8eca4acb28e4":"Excelsecu eSecu FIDO2 Fingerprint Security Key","2194b428-9397-4046-8f39-007a1605a482":"IDPrime 931 Fido","234cd403-35a2-4cc2-8015-77ea280c77f5":"Feitian ePass FIDO2-NFC Series (CTAP2.1, CTAP2.0, U2F)","23786452-f02d-4344-87ed-aaf703726881":"SafeNet eToken Fusion CC","2772ce93-eb4b-4090-8b73-330f48477d73":"Security Key NFC by Yubico - Enterprise Edition Preview","2c0df832-92de-4be1-8412-88a8f074df4a":"Feitian FIDO Smart Card","2d3bec26-15ee-4f5d-88b2-53622490270b":"HID Crescendo Key V2","2fc0579f-8113-47ea-b116-bb5a8db9202a":"YubiKey 5 Series with NFC","2ffd6452-01da-471f-821b-ea4bf6c8676a":"IDPrime 941 Fido","30b5035e-d297-4fc1-b00b-addc96ba6a97":"OneSpan FIDO Touch","30b5035e-d297-4ff1-b00b-addc96ba6a98":"OneSpan DIGIPASS FX1 BIO","3124e301-f14e-4e38-876d-fbeeb090e7bf":"YubiKey 5 Series with Lightning Preview","31c3f7ff-bf15-4327-83ec-9336abcbcd34":"WinMagic FIDO Eazy - Software","341e4da9-3c2e-8103-5a9f-aad887135200":"Ledger Nano S FIDO2 Authenticator","34f5766d-1536-4a24-9033-0e294e510fb0":"YubiKey 5 Series with NFC Preview","361a3082-0278-4583-a16f-72a527f973e4":"eWBM eFA500 FIDO2 Authenticator","3789da91-f943-46bc-95c3-50ea2012f03a":"NEOWAVE Winkeo FIDO2","39a5647e-1853-446c-a1f6-a79bae9f5bc7":"IDmelon","3b1adb99-0dfe-46fd-90b8-7f7614a4de2a":"GoTrust Idem Key FIDO2 Authenticator","3e078ffd-4c54-4586-8baa-a77da113aec5":"Hideez Key 3 FIDO2","3e22415d-7fdf-4ea4-8a0c-dd60c4249b9d":"Feitian iePass FIDO Authenticator","3f59672f-20aa-4afe-b6f4-7e5e916b6d98":"Arculus FIDO 2.1 Key Card [P71]","42b4fb4a-2866-43b2-9bf7-6c6669c2e5d3":"Google Titan Security Key v2","454e5346-4944-4ffd-6c93-8e9267193e9a":"Ensurity ThinC","454e5346-4944-4ffd-6c93-8e9267193e9b":"Ensurity AUTH BioPro","47ab2fb4-66ac-4184-9ae1-86be814012d5":"Security Key NFC by Yubico - Enterprise Edition","4b3f8944-d4f2-4d21-bb19-764a986ec160":"KeyXentic FIDO2 Secp256R1 FIDO2 CTAP2 Authenticator","4c0cf95d-2f40-43b5-ba42-4c83a11c04ba":"Feitian BioPass FIDO2 Pro Authenticator","4c50ff10-1057-4fc6-b8ed-43a529530c3c":"ImproveID Authenticator","4d41190c-7beb-4a84-8018-adf265a6352d":"Thales IDPrime FIDO Bio","4e768f2c-5fab-48b3-b300-220eb487752b":"Hideez Key 4 FIDO2 SDK","504d7149-4e4c-3841-4555-55445a677357":"WiSECURE AuthTron USB FIDO2 Authenticator","50726f74-6f6e-5061-7373-50726f746f6e":"Proton Pass","50a45b0c-80e7-f944-bf29-f552bfa2e048":"ACS FIDO Authenticator","516d3969-5a57-5651-5958-4e7a49434167":"SmartDisplayer BobeePass FIDO2 Authenticator","531126d6-e717-415c-9320-3d9aa6981239":"Dashlane","53414d53-554e-4700-0000-000000000000":"Samsung Pass","5343502d-5343-5343-6172-644649444f32":"ESS Smart Card Inc. Authenticator","54d9fee8-e621-4291-8b18-7157b99c5bec":"HID Crescendo Enabled","5626bed4-e756-430b-a7ff-ca78c8b12738":"VALMIDO PRO FIDO","58b44d0b-0a7c-f33a-fd48-f7153c871352":"Ledger Nano S Plus FIDO2 Authenticator","5b0e46ba-db02-44ac-b979-ca9b84f5e335":"YubiKey 5 FIPS Series with Lightning Preview","5ca1ab1e-1337-fa57-f1d0-a117e71ca702":"Allthenticator App: roaming BLE FIDO2 Allthenticator for Windows, Mac, Linux, and Allthenticate door readers","5d629218-d3a5-11ed-afa1-0242ac120002":"Swissbit iShield Key Pro","5fdb81b8-53f0-4967-a881-f5ec26fe4d18":"VinCSS FIDO2 Authenticator","6002f033-3c07-ce3e-d0f7-0ffe5ed42543":"Excelsecu eSecu FIDO2 Fingerprint Key","6028b017-b1d4-4c02-b4b3-afcdafc96bb2":"Windows Hello","61250591-b2bc-4456-b719-0b17be90bb30":"eWBM eFPA FIDO2 Authenticator","62e54e98-c209-4df3-b692-de71bb6a8528":"YubiKey 5 FIPS Series with NFC Preview","664d9f67-84a2-412a-9ff7-b4f7d8ee6d05":"OpenSK authenticator","66a0ccb3-bd6a-191f-ee06-e375c50b9846":"Thales Bio iOS SDK","692db549-7ae5-44d5-a1e5-dd20a493b723":"HID Crescendo Key","69700f79-d1fb-472e-bd9b-a3a3b9a9eda0":"Pone Biometrics OFFPAD Authenticator","6d44ba9b-f6ec-2e49-b930-0c8fe920cb73":"Security Key by Yubico with NFC","6dae43be-af9c-417b-8b9f-1b611168ec60":"Dapple Authenticator from Dapple Security Inc.","73402251-f2a8-4f03-873e-3cb6db604b03":"uTrust FIDO2 Security Key","73bb0cd4-e502-49b8-9c6f-b59445bf720b":"YubiKey 5 FIPS Series","74820b05-a6c9-40f9-8fb0-9f86aca93998":"SafeNet eToken Fusion","760eda36-00aa-4d29-855b-4012a182cdeb":"Security Key NFC by Yubico Preview","77010bd7-212a-4fc9-b236-d2ca5e9d4084":"Feitian BioPass FIDO2 Authenticator","771b48fd-d3d4-4f74-9232-fc157ab0507a":"Edge on Mac","7d1351a6-e097-4852-b8bf-c9ac5c9ce4a3":"YubiKey Bio Series - Multi-protocol Edition","7d2afadd-bf6b-44a2-a66b-e831fceb8eff":"Taglio CTAP2.1 EP","7e3f3d30-3557-4442-bdae-139312178b39":"RSA DS100","820d89ed-d65a-409e-85cb-f73f0578f82a":"IDmelon iOS Authenticator","833b721a-ff5f-4d00-bb2e-bdda3ec01e29":"Feitian ePass FIDO2 Authenticator","83c47309-aabb-4108-8470-8be838b573cb":"YubiKey Bio Series (Enterprise Profile)","85203421-48f9-4355-9bc8-8a53846e5083":"YubiKey 5 FIPS Series with Lightning","87dbc5a1-4c94-4dc8-8a47-97d800fd1f3c":"eWBM eFA320 FIDO2 Authenticator","8836336a-f590-0921-301d-46427531eee6":"Thales Bio Android SDK","8876631b-d4a0-427f-5773-0ec71c9e0279":"Solo Secp256R1 FIDO2 CTAP2 Authenticator","88bbd2f0-342a-42e7-9729-dd158be5407a":"Precision InnaIT Key FIDO 2 Level 2 certified","891494da-2c90-4d31-a9cd-4eab0aed1309":"S\xE9same","8976631b-d4a0-427f-5773-0ec71c9e0279":"Solo Tap Secp256R1 FIDO2 CTAP2 Authenticator","89b19028-256b-4025-8872-255358d950e4":"Sentry Enterprises CTAP2 Authenticator","8c97a730-3f7b-41a6-87d6-1e9b62bda6f0":"FT-JCOS FIDO Fingerprint Card","8d1b1fcb-3c76-49a9-9129-5515b346aa02":"IDEMIA ID-ONE Card","91ad6b93-264b-4987-8737-3a690cad6917":"Token Ring FIDO2 Authenticator","931327dd-c89b-406c-a81e-ed7058ef36c6":"Swissbit iShield Key FIDO2","95442b2e-f15e-4def-b270-efb106facb4e":"eWBM eFA310 FIDO2 Authenticator","95e4d58c-056e-4a65-866d-f5a69659e880":"TruU Windows Authenticator","970c8d9c-19d2-46af-aa32-3f448db49e35":"WinMagic FIDO Eazy - TPM","973446ca-e21c-9a9b-99f5-9b985a67af0f":"ACS FIDO Authenticator Card","9876631b-d4a0-427f-5773-0ec71c9e0279":"Somu Secp256R1 FIDO2 CTAP2 Authenticator","998f358b-2dd2-4cbe-a43a-e8107438dfb3":"OnlyKey Secp256R1 FIDO2 CTAP2 Authenticator","99bf4610-ec26-4252-b31f-7380ccd59db5":"ZTPass Card","9c835346-796b-4c27-8898-d6032f515cc5":"Cryptnox FIDO2","9d3df6ba-282f-11ed-a261-0242ac120002":"Arculus FIDO2/U2F Key Card","9ddd1817-af5a-4672-a2b9-3e3dd95000a9":"Windows Hello","9f0d8150-baa5-4c00-9299-ad62c8bb4e87":"GoTrust Idem Card FIDO2 Authenticator","9f77e279-a6e2-4d58-b700-31e5943c6a98":"Hyper FIDO Pro","a02167b9-ae71-4ac7-9a07-06432ebb6f1c":"YubiKey 5 Series with Lightning","a1f52be5-dfab-4364-b51c-2bd496b14a56":"OCTATCO EzFinger2 FIDO2 AUTHENTICATOR","a25342c0-3cdc-4414-8e46-f4807fca511c":"YubiKey 5 Series with NFC","a3975549-b191-fd67-b8fb-017e2917fdb3":"Excelsecu eSecu FIDO2 NFC Security Key","a4e9fc6d-4cbe-4758-b8ba-37598bb5bbaa":"Security Key NFC by Yubico","ab32f0c6-2239-afbb-c470-d2ef4e254db6":"TEST (DUMMY RECORD)","ab32f0c6-2239-afbb-c470-d2ef4e254db7":"TOKEN2 FIDO2 Security Key","adce0002-35bc-c60a-648b-0b25f1f05503":"Chrome on Mac","aeb6569c-f8fb-4950-ac60-24ca2bbe2e52":"HID Crescendo C2300","b267239b-954f-4041-a01b-ee4f33c145b6":"authenton1 - CTAP2.1","b50d5e0a-7f81-4959-9b12-f45407407503":"IDPrime 3940 FIDO","b5397666-4885-aa6b-cebf-e52262a439a2":"Chromium Browser","b6ede29c-3772-412c-8a78-539c1f4c62d2":"Feitian BioPass FIDO2 Plus Authenticator","b84e4048-15dc-4dd0-8640-f4f60813c8af":"NordPass","b92c3f9a-c014-4056-887f-140a2501163b":"Security Key by Yubico","b93fd961-f2e6-462f-b122-82002247de78":"Android Authenticator with SafetyNet Attestation","ba76a271-6eb6-4171-874d-b6428dbe3437":"ATKey.ProS","ba86dc56-635f-4141-aef6-00227b1b9af6":"TruU Windows Authenticator","bada5566-a7aa-401f-bd96-45619a55120d":"1Password","bbf4b6a7-679d-f6fc-c4f2-8ac0ddf9015a":"Excelsecu eSecu FIDO2 PRO Security Key","bc2fe499-0d8e-4ffe-96f3-94a82840cf8c":"OCTATCO EzQuant FIDO2 AUTHENTICATOR","be727034-574a-f799-5c76-0929e0430973":"Crayonic KeyVault K1 (USB-NFC-BLE FIDO2 Authenticator)","c1f9a0bc-1dd2-404a-b27f-8e29047a43fd":"YubiKey 5 FIPS Series with NFC","c5703116-972b-4851-a3e7-ae1259843399":"NEOWAVE Badgeo FIDO2","c5ef55ff-ad9a-4b9f-b580-adebafe026d0":"YubiKey 5 Series with Lightning","c80dbd9a-533f-4a17-b941-1a2f1c7cedff":"HID Crescendo C3000","ca4cff1b-5a81-4404-8194-59aabcf1660b":"IDPrime 3930 FIDO","ca87cb70-4c1b-4579-a8e8-4efdd7c007e0":"FIDO Alliance TruU Sample FIDO2 Authenticator","cb69481e-8ff7-4039-93ec-0a2729a154a8":"YubiKey 5 Series","cc45f64e-52a2-451b-831a-4edd8022a202":"ToothPic Passkey Provider","cd69adb5-3c7a-deb9-3177-6800ea6cb72a":"Thales PIN Android SDK","cdbdaea2-c415-5073-50f7-c04e968640b6":"Excelsecu eSecu FIDO2 Security Key","cfcb13a2-244f-4b36-9077-82b79d6a7de7":"USB/NFC Passcode Authenticator","d384db22-4d50-ebde-2eac-5765cf1e2a44":"Excelsecu eSecu FIDO2 Fingerprint Security Key","d41f5a69-b817-4144-a13c-9ebd6d9254d6":"ATKey.Card CTAP2.0","d548826e-79b4-db40-a3d8-11116f7e8349":"Bitwarden","d61d3b87-3e7c-4aea-9c50-441c371903ad":"KeyVault Secp256R1 FIDO2 CTAP2 Authenticator","d7a423ad-3e19-4492-9200-78137dccc136":"VivoKey Apex FIDO2","d821a7d4-e97c-4cb6-bd82-4237731fd4be":"Hyper FIDO Bio Security Key","d8522d9f-575b-4866-88a9-ba99fa02f35b":"YubiKey Bio Series","d91c5288-0ef0-49b7-b8ae-21ca0aa6b3f3":"KEY-ID FIDO2 Authenticator","d94a29d9-52dd-4247-9c2d-8b818b610389":"VeriMark Guard Fingerprint Key","da1fa263-8b25-42b6-a820-c0036f21ba7f":"ATKey.Card NFC","dd4ec289-e01d-41c9-bb89-70fa845d4bf2":"iCloud Keychain (Managed)","e1a96183-5016-4f24-b55b-e3ae23614cc6":"ATKey.Pro CTAP2.0","e416201b-afeb-41ca-a03d-2281c28322aa":"ATKey.Pro CTAP2.1","e77e3c64-05e3-428b-8824-0cbeb04b829d":"Security Key NFC by Yubico","e86addcd-7711-47e5-b42a-c18257b0bf61":"IDCore 3121 Fido","ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4":"Google Password Manager","eabb46cc-e241-80bf-ae9e-96fa6d2975cf":"TOKEN2 PIN Plus Security Key Series ","eb3b131e-59dc-536a-d176-cb7306da10f5":"ellipticSecure MIRkey USB Authenticator","ec31b4cc-2acc-4b8e-9c01-bade00ccbe26":"KeyXentic FIDO2 Secp256R1 FIDO2 CTAP2 Authenticator","ee041bce-25e5-4cdb-8f86-897fd6418464":"Feitian ePass FIDO2-NFC Authenticator","ee882879-721c-4913-9775-3dfcce97072a":"YubiKey 5 Series","efb96b10-a9ee-4b6c-a4a9-d32125ccd4a4":"Safenet eToken FIDO","f3809540-7f14-49c1-a8b3-8f813b225541":"Enpass","f4c63eff-d26c-4248-801c-3736c7eaa93a":"FIDO KeyPass S3","f56f58b3-d711-4afc-ba7d-6ac05f88cb19":"WinMagic FIDO Eazy - Phone","f7c558a0-f465-11e8-b568-0800200c9a66":"KONAI Secp256R1 FIDO2 Conformance Testing CTAP2 Authenticator","f8a011f3-8c0a-4d15-8006-17111f9edc7d":"Security Key by Yubico","fa2b99dc-9e39-4257-8f92-4a30d23c4118":"YubiKey 5 Series with NFC","fbefdf68-fe86-0106-213e-4d5fa24cbe2e":"Excelsecu eSecu FIDO2 NFC Security Key","fbfc3007-154e-4ecc-8c0b-6e020557d7bd":"iCloud Keychain","fcb1bcb4-f370-078c-6993-bc24d0ae3fbe":"Ledger Nano X FIDO2 Authenticator","fdb141b2-5d84-443e-8a35-4698c205a502":"KeePassXC","fec067a1-f1d0-4c5e-b4c0-cc3237475461":"KX701 SmartToken FIDO"};var Y=new TextDecoder("utf-8");function S(e){return typeof e=="string"&&(e=o(e)),JSON.parse(Y.decode(e))}function b(e){typeof e=="string"&&(e=o(e));let t=new DataView(e.slice(32,33)).getUint8(0);return{rpIdHash:M(e),flags:{userPresent:!!(t&1),userVerified:!!(t&4),backupEligibility:!!(t&8),backupState:!!(t&16),attestedData:!!(t&64),extensionsIncluded:!!(t&128)},signCount:new DataView(e.slice(33,37)).getUint32(0,!1),aaguid:W(e)}}function M(e){return n(e.slice(0,32))}function W(e){if(e.byteLength<53)return"00000000-0000-0000-0000-000000000000";let t=e.slice(37,53),a=C(t);return`${a.substring(0,8)}-${a.substring(8,12)}-${a.substring(12,16)}-${a.substring(16,20)}-${a.substring(20,32)}`}function E(e){switch(e){case-7:return"ES256";case-8:return"EdDSA";case-257:return"RS256";default:throw new Error(`Unknown algorithm code: ${e}`)}}function $(e){let t=b(e.response.authenticatorData);return N(e,t)}function N(e,t){let a=t.aaguid;return{authenticator:{aaguid:a,counter:t.signCount,icon_light:"https://webauthn.passwordless.id/authenticators/"+a+"-light.png",icon_dark:"https://webauthn.passwordless.id/authenticators/"+a+"-dark.png",name:p[a]??"Unknown"},credential:{id:e.id,publicKey:e.response.publicKey,algorithm:E(e.response.publicKeyAlgorithm),transports:e.response.transports},synced:t.flags.backupEligibility,user:e.user,userVerified:t.flags.userVerified}}function I(e,t){return{credentialId:e.id,userId:e.response.userHandle,counter:t.signCount,userVerified:t.flags.userVerified,authenticatorAttachment:e.authenticatorAttachment}}function G(e){let t=b(e.response.authenticatorData);return I(e,t)}function z(){let e=crypto.getRandomValues(new Uint8Array(18));return n(e)}async function J(e,t){if(typeof e=="function"){let a=e(t);return a instanceof Promise?await a:a}return e===t}async function m(e,t){return!await J(e,t)}async function j(e,t){let a=S(e.response.clientDataJSON),r=b(e.response.authenticatorData);if(!r.aaguid)throw new Error("Unexpected errror, no AAGUID.");if(a.type!=="webauthn.create")throw new Error(`Unexpected ClientData type: ${a.type}`);if(await m(t.origin,a.origin))throw new Error(`Unexpected ClientData origin: ${a.origin}`);if(await m(t.challenge,a.challenge))throw new Error(`Unexpected ClientData challenge: ${a.challenge}`);return h.toRegistrationInfo(e,r)}async function X(e,t,a){if(e.id!==t.id)throw new Error(`Credential ID mismatch: ${e.id} vs ${t.id}`);if(!await T({algorithm:t.algorithm,publicKey:t.publicKey,authenticatorData:e.response.authenticatorData,clientData:e.response.clientDataJSON,signature:e.response.signature,verbose:a.verbose}))throw new Error(`Invalid signature: ${e.response.signature}`);let i=S(e.response.clientDataJSON),c=b(e.response.authenticatorData);if(a.verbose&&(console.debug(i),console.debug(c)),i.type!=="webauthn.get")throw new Error(`Unexpected clientData type: ${i.type}`);if(await m(a.origin,i.origin))throw new Error(`Unexpected ClientData origin: ${i.origin}`);if(await m(a.challenge,i.challenge))throw new Error(`Unexpected ClientData challenge: ${i.challenge}`);let d=a.domain??new URL(i.origin).hostname,l=n(await A(f(d)));if(c.rpIdHash!==l)throw new Error(`Unexpected RpIdHash: ${c.rpIdHash} vs ${l}`);if(!c.flags.userPresent)throw new Error("Unexpected authenticator flags: missing userPresent");if(!c.flags.userVerified&&a.userVerified)throw new Error("Unexpected authenticator flags: missing userVerified");if(a.counter&&c.signCount<=a.counter)throw new Error(`Unexpected authenticator counter: ${c.signCount} (should be > ${a.counter})`);return I(e,c)}function _(e){switch(e){case"RS256":return{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"};case"ES256":return{name:"ECDSA",namedCurve:"P-256",hash:"SHA-256"};default:throw new Error(`Unknown or unsupported crypto algorithm: ${e}. Only 'RS256' and 'ES256' are supported.`)}}async function q(e,t){let a=o(t);return crypto.subtle.importKey("spki",a,e,!1,["verify"])}async function T({algorithm:e,publicKey:t,authenticatorData:a,clientData:r,signature:i,verbose:c}){let d=_(e),l=await q(d,t);c&&console.debug(l);let R=await A(o(r)),P=O(o(a),R);c&&(console.debug("Crypto Algo: "+JSON.stringify(d)),console.debug("Public key: "+t),console.debug("Data: "+n(P)),console.debug("Signature: "+i));let D=o(i);return e=="ES256"&&(D=Z(D)),await crypto.subtle.verify(d,l,D,P)}function Z(e){let t=new Uint8Array(e),a=t[4]===0?5:4,r=a+32,i=t[r+2]===0?r+3:r+2,c=t.slice(a,r),d=t.slice(i);return new Uint8Array([...c,...d])}var Q={client:w,server:F,parsers:h,utils:u,authenticatorMetadata:p},se=Q;export{p as authenticatorMetadata,w as client,se as default,h as parsers,F as server,u as utils}; +/*passwordless-id/webauthn@2.1.2*/ +var v=Object.defineProperty;var y=(e,t)=>{for(var a in t)v(e,a,{get:t[a],enumerable:!0})};var w={};y(w,{authenticate:()=>Y,isAutocompleteAvailable:()=>B,isAvailable:()=>H,isLocalAuthenticator:()=>V,register:()=>L});var u={};y(u,{bufferToHex:()=>C,concatenateBuffers:()=>O,isBase64url:()=>g,parseBase64url:()=>o,parseBuffer:()=>K,sha256:()=>A,toBase64url:()=>n,toBuffer:()=>f});function f(e){return Uint8Array.from(e,t=>t.charCodeAt(0)).buffer}function K(e){return String.fromCharCode(...new Uint8Array(e))}function g(e){return e.match(/^[a-zA-Z0-9\-_]+=*$/)!==null}function n(e){return btoa(K(e)).replaceAll("+","-").replaceAll("/","_")}function o(e){return e=e.replaceAll("-","+").replaceAll("_","/"),f(atob(e))}async function A(e){return await crypto.subtle.digest("SHA-256",e)}function C(e){return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}function O(e,t){var a=new Uint8Array(e.byteLength+t.byteLength);return a.set(new Uint8Array(e),0),a.set(new Uint8Array(t),e.byteLength),a}function H(){return!!window.PublicKeyCredential}async function V(){return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}function k(e){if(!(!e||e.length===0))return e.includes("client-device")?e.includes("security-key")||e.includes("hybrid")?void 0:"platform":"cross-platform"}var s=null;async function L(e){if(!e.challenge)throw new Error('"challenge" required');if(!e.user)throw new Error('"user" required');if(!g(e.challenge))throw new Error("Provided challenge is not properly encoded in Base64url");let t=typeof e.user=="string"?{name:e.user}:e.user;t.id||(t.id=crypto.randomUUID());let a={challenge:o(e.challenge),rp:{id:e.domain??window.location.hostname,name:e.domain??window.location.hostname},user:{id:f(t.id),name:t.name,displayName:t.displayName??t.name},hints:e.hints,pubKeyCredParams:[{alg:-7,type:"public-key"},{alg:-257,type:"public-key"}],timeout:e.timeout,authenticatorSelection:{userVerification:e.userVerification,authenticatorAttachment:k(e.hints),residentKey:e.discoverable??"preferred",requireResidentKey:e.discoverable==="required"},attestation:"direct"};console.debug(a),s?.abort("Cancel ongoing authentication"),s=new AbortController;let r=await navigator.credentials.create({publicKey:a,signal:s?.signal}),i=r.response;if(s=null,console.debug(r),r.type!="public-key")throw"Unexpected credential type!";let c=i.getPublicKey();if(!c)throw"Non-compliant browser or authenticator!";return{type:r.type,id:r.id,rawId:n(r.rawId),authenticatorAttachment:r.authenticatorAttachment,clientExtensionResults:r.getClientExtensionResults(),response:{attestationObject:n(i.attestationObject),authenticatorData:n(i.getAuthenticatorData()),clientDataJSON:n(i.clientDataJSON),publicKey:n(c),publicKeyAlgorithm:i.getPublicKeyAlgorithm(),transports:i.getTransports()},user:t}}async function B(){return PublicKeyCredential.isConditionalMediationAvailable&&PublicKeyCredential.isConditionalMediationAvailable()}async function Y(e){if(!g(e.challenge))throw new Error("Provided challenge is not properly encoded in Base64url");if(e.autocomplete&&!await B())throw new Error("PAsskeys autocomplete with conditional mediation is not available in this browser.");let t={challenge:o(e.challenge),rpId:e.domain??window.location.hostname,allowCredentials:e.allowCredentials?.map(M),hints:e.hints,userVerification:e.userVerification,timeout:e.timeout};console.debug(t),s?.abort("Cancel ongoing authentication"),e.autocomplete&&(s=new AbortController);let a=await navigator.credentials.get({publicKey:t,mediation:e.autocomplete?"conditional":void 0,signal:s?.signal});if(a.type!="public-key")throw"Unexpected credential type!";s=null,console.debug(a);let r=a.response;return{clientExtensionResults:a.getClientExtensionResults(),id:a.id,rawId:n(a.rawId),type:a.type,authenticatorAttachment:a.authenticatorAttachment,response:{authenticatorData:n(r.authenticatorData),clientDataJSON:n(r.clientDataJSON),signature:n(r.signature),userHandle:r.userHandle?n(r.userHandle):void 0}}}function M(e){return typeof e=="string"?{id:o(e),type:"public-key"}:{id:o(e.id),type:"public-key",transports:e.transports}}var F={};y(F,{parseCryptoKey:()=>R,randomChallenge:()=>J,verifyAuthentication:()=>q,verifyRegistration:()=>_,verifySignature:()=>U});var l={};y(l,{getAlgoName:()=>E,parseAuthentication:()=>j,parseAuthenticator:()=>b,parseClient:()=>S,parseRegistration:()=>z,toAuthenticationInfo:()=>I,toRegistrationInfo:()=>N});var p={"00000000-0000-0000-0000-000000000000":"Unknown authenticator","0076631b-d4a0-427f-5773-0ec71c9e0279":"HYPR FIDO2 Authenticator","07a9f89c-6407-4594-9d56-621d5f1e358b":"NXP Semiconductros FIDO2 Conformance Testing CTAP2 Authenticator","08987058-cadc-4b81-b6e1-30de50dcbe96":"Windows Hello","092277e5-8437-46b5-b911-ea64b294acb7":"Taglio CTAP2.1 CS","09591fc6-9811-48f7-8f57-b9f23df6413f":"Pone Biometrics OFFPAD Authenticator","0acf3011-bc60-f375-fb53-6f05f43154e0":"Nymi FIDO2 Authenticator","0bb43545-fd2c-4185-87dd-feb0b2916ace":"Security Key NFC by Yubico - Enterprise Edition","0d9b2e56-566b-c393-2940-f821b7f15d6d":"Excelsecu eSecu FIDO2 Pro Security Key","0ea242b4-43c4-4a1b-8b17-dd6d0b6baec6":"Keeper","1105e4ed-af1d-02ff-ffff-ffffffffffff":"Egomet FIDO2 Authenticator for Android","12ded745-4bed-47d4-abaa-e713f51d6393":"Feitian AllinOne FIDO2 Authenticator","149a2021-8ef6-4133-96b8-81f8d5b7f1f5":"Security Key by Yubico with NFC","17290f1e-c212-34d0-1423-365d729f09d9":"Thales PIN iOS SDK","175cd298-83d2-4a26-b637-313c07a6434e":"Chunghwa Telecom FIDO2 Smart Card Authenticator","19083c3d-8383-4b18-bc03-8f1c9ab2fd1b":"YubiKey 5 Series","1c086528-58d5-f211-823c-356786e36140":"Atos CardOS FIDO2","20f0be98-9af9-986a-4b42-8eca4acb28e4":"Excelsecu eSecu FIDO2 Fingerprint Security Key","2194b428-9397-4046-8f39-007a1605a482":"IDPrime 931 Fido","234cd403-35a2-4cc2-8015-77ea280c77f5":"Feitian ePass FIDO2-NFC Series (CTAP2.1, CTAP2.0, U2F)","23786452-f02d-4344-87ed-aaf703726881":"SafeNet eToken Fusion CC","2772ce93-eb4b-4090-8b73-330f48477d73":"Security Key NFC by Yubico - Enterprise Edition Preview","2c0df832-92de-4be1-8412-88a8f074df4a":"Feitian FIDO Smart Card","2d3bec26-15ee-4f5d-88b2-53622490270b":"HID Crescendo Key V2","2fc0579f-8113-47ea-b116-bb5a8db9202a":"YubiKey 5 Series with NFC","2ffd6452-01da-471f-821b-ea4bf6c8676a":"IDPrime 941 Fido","30b5035e-d297-4fc1-b00b-addc96ba6a97":"OneSpan FIDO Touch","30b5035e-d297-4ff1-b00b-addc96ba6a98":"OneSpan DIGIPASS FX1 BIO","3124e301-f14e-4e38-876d-fbeeb090e7bf":"YubiKey 5 Series with Lightning Preview","31c3f7ff-bf15-4327-83ec-9336abcbcd34":"WinMagic FIDO Eazy - Software","341e4da9-3c2e-8103-5a9f-aad887135200":"Ledger Nano S FIDO2 Authenticator","34f5766d-1536-4a24-9033-0e294e510fb0":"YubiKey 5 Series with NFC Preview","361a3082-0278-4583-a16f-72a527f973e4":"eWBM eFA500 FIDO2 Authenticator","3789da91-f943-46bc-95c3-50ea2012f03a":"NEOWAVE Winkeo FIDO2","39a5647e-1853-446c-a1f6-a79bae9f5bc7":"IDmelon","3b1adb99-0dfe-46fd-90b8-7f7614a4de2a":"GoTrust Idem Key FIDO2 Authenticator","3e078ffd-4c54-4586-8baa-a77da113aec5":"Hideez Key 3 FIDO2","3e22415d-7fdf-4ea4-8a0c-dd60c4249b9d":"Feitian iePass FIDO Authenticator","3f59672f-20aa-4afe-b6f4-7e5e916b6d98":"Arculus FIDO 2.1 Key Card [P71]","42b4fb4a-2866-43b2-9bf7-6c6669c2e5d3":"Google Titan Security Key v2","454e5346-4944-4ffd-6c93-8e9267193e9a":"Ensurity ThinC","454e5346-4944-4ffd-6c93-8e9267193e9b":"Ensurity AUTH BioPro","47ab2fb4-66ac-4184-9ae1-86be814012d5":"Security Key NFC by Yubico - Enterprise Edition","4b3f8944-d4f2-4d21-bb19-764a986ec160":"KeyXentic FIDO2 Secp256R1 FIDO2 CTAP2 Authenticator","4c0cf95d-2f40-43b5-ba42-4c83a11c04ba":"Feitian BioPass FIDO2 Pro Authenticator","4c50ff10-1057-4fc6-b8ed-43a529530c3c":"ImproveID Authenticator","4d41190c-7beb-4a84-8018-adf265a6352d":"Thales IDPrime FIDO Bio","4e768f2c-5fab-48b3-b300-220eb487752b":"Hideez Key 4 FIDO2 SDK","504d7149-4e4c-3841-4555-55445a677357":"WiSECURE AuthTron USB FIDO2 Authenticator","50726f74-6f6e-5061-7373-50726f746f6e":"Proton Pass","50a45b0c-80e7-f944-bf29-f552bfa2e048":"ACS FIDO Authenticator","516d3969-5a57-5651-5958-4e7a49434167":"SmartDisplayer BobeePass FIDO2 Authenticator","531126d6-e717-415c-9320-3d9aa6981239":"Dashlane","53414d53-554e-4700-0000-000000000000":"Samsung Pass","5343502d-5343-5343-6172-644649444f32":"ESS Smart Card Inc. Authenticator","54d9fee8-e621-4291-8b18-7157b99c5bec":"HID Crescendo Enabled","5626bed4-e756-430b-a7ff-ca78c8b12738":"VALMIDO PRO FIDO","58b44d0b-0a7c-f33a-fd48-f7153c871352":"Ledger Nano S Plus FIDO2 Authenticator","5b0e46ba-db02-44ac-b979-ca9b84f5e335":"YubiKey 5 FIPS Series with Lightning Preview","5ca1ab1e-1337-fa57-f1d0-a117e71ca702":"Allthenticator App: roaming BLE FIDO2 Allthenticator for Windows, Mac, Linux, and Allthenticate door readers","5d629218-d3a5-11ed-afa1-0242ac120002":"Swissbit iShield Key Pro","5fdb81b8-53f0-4967-a881-f5ec26fe4d18":"VinCSS FIDO2 Authenticator","6002f033-3c07-ce3e-d0f7-0ffe5ed42543":"Excelsecu eSecu FIDO2 Fingerprint Key","6028b017-b1d4-4c02-b4b3-afcdafc96bb2":"Windows Hello","61250591-b2bc-4456-b719-0b17be90bb30":"eWBM eFPA FIDO2 Authenticator","62e54e98-c209-4df3-b692-de71bb6a8528":"YubiKey 5 FIPS Series with NFC Preview","664d9f67-84a2-412a-9ff7-b4f7d8ee6d05":"OpenSK authenticator","66a0ccb3-bd6a-191f-ee06-e375c50b9846":"Thales Bio iOS SDK","692db549-7ae5-44d5-a1e5-dd20a493b723":"HID Crescendo Key","69700f79-d1fb-472e-bd9b-a3a3b9a9eda0":"Pone Biometrics OFFPAD Authenticator","6d44ba9b-f6ec-2e49-b930-0c8fe920cb73":"Security Key by Yubico with NFC","6dae43be-af9c-417b-8b9f-1b611168ec60":"Dapple Authenticator from Dapple Security Inc.","73402251-f2a8-4f03-873e-3cb6db604b03":"uTrust FIDO2 Security Key","73bb0cd4-e502-49b8-9c6f-b59445bf720b":"YubiKey 5 FIPS Series","74820b05-a6c9-40f9-8fb0-9f86aca93998":"SafeNet eToken Fusion","760eda36-00aa-4d29-855b-4012a182cdeb":"Security Key NFC by Yubico Preview","77010bd7-212a-4fc9-b236-d2ca5e9d4084":"Feitian BioPass FIDO2 Authenticator","771b48fd-d3d4-4f74-9232-fc157ab0507a":"Edge on Mac","7d1351a6-e097-4852-b8bf-c9ac5c9ce4a3":"YubiKey Bio Series - Multi-protocol Edition","7d2afadd-bf6b-44a2-a66b-e831fceb8eff":"Taglio CTAP2.1 EP","7e3f3d30-3557-4442-bdae-139312178b39":"RSA DS100","820d89ed-d65a-409e-85cb-f73f0578f82a":"IDmelon iOS Authenticator","833b721a-ff5f-4d00-bb2e-bdda3ec01e29":"Feitian ePass FIDO2 Authenticator","83c47309-aabb-4108-8470-8be838b573cb":"YubiKey Bio Series (Enterprise Profile)","85203421-48f9-4355-9bc8-8a53846e5083":"YubiKey 5 FIPS Series with Lightning","87dbc5a1-4c94-4dc8-8a47-97d800fd1f3c":"eWBM eFA320 FIDO2 Authenticator","8836336a-f590-0921-301d-46427531eee6":"Thales Bio Android SDK","8876631b-d4a0-427f-5773-0ec71c9e0279":"Solo Secp256R1 FIDO2 CTAP2 Authenticator","88bbd2f0-342a-42e7-9729-dd158be5407a":"Precision InnaIT Key FIDO 2 Level 2 certified","891494da-2c90-4d31-a9cd-4eab0aed1309":"S\xE9same","8976631b-d4a0-427f-5773-0ec71c9e0279":"Solo Tap Secp256R1 FIDO2 CTAP2 Authenticator","89b19028-256b-4025-8872-255358d950e4":"Sentry Enterprises CTAP2 Authenticator","8c97a730-3f7b-41a6-87d6-1e9b62bda6f0":"FT-JCOS FIDO Fingerprint Card","8d1b1fcb-3c76-49a9-9129-5515b346aa02":"IDEMIA ID-ONE Card","91ad6b93-264b-4987-8737-3a690cad6917":"Token Ring FIDO2 Authenticator","931327dd-c89b-406c-a81e-ed7058ef36c6":"Swissbit iShield Key FIDO2","95442b2e-f15e-4def-b270-efb106facb4e":"eWBM eFA310 FIDO2 Authenticator","95e4d58c-056e-4a65-866d-f5a69659e880":"TruU Windows Authenticator","970c8d9c-19d2-46af-aa32-3f448db49e35":"WinMagic FIDO Eazy - TPM","973446ca-e21c-9a9b-99f5-9b985a67af0f":"ACS FIDO Authenticator Card","9876631b-d4a0-427f-5773-0ec71c9e0279":"Somu Secp256R1 FIDO2 CTAP2 Authenticator","998f358b-2dd2-4cbe-a43a-e8107438dfb3":"OnlyKey Secp256R1 FIDO2 CTAP2 Authenticator","99bf4610-ec26-4252-b31f-7380ccd59db5":"ZTPass Card","9c835346-796b-4c27-8898-d6032f515cc5":"Cryptnox FIDO2","9d3df6ba-282f-11ed-a261-0242ac120002":"Arculus FIDO2/U2F Key Card","9ddd1817-af5a-4672-a2b9-3e3dd95000a9":"Windows Hello","9f0d8150-baa5-4c00-9299-ad62c8bb4e87":"GoTrust Idem Card FIDO2 Authenticator","9f77e279-a6e2-4d58-b700-31e5943c6a98":"Hyper FIDO Pro","a02167b9-ae71-4ac7-9a07-06432ebb6f1c":"YubiKey 5 Series with Lightning","a1f52be5-dfab-4364-b51c-2bd496b14a56":"OCTATCO EzFinger2 FIDO2 AUTHENTICATOR","a25342c0-3cdc-4414-8e46-f4807fca511c":"YubiKey 5 Series with NFC","a3975549-b191-fd67-b8fb-017e2917fdb3":"Excelsecu eSecu FIDO2 NFC Security Key","a4e9fc6d-4cbe-4758-b8ba-37598bb5bbaa":"Security Key NFC by Yubico","ab32f0c6-2239-afbb-c470-d2ef4e254db6":"TEST (DUMMY RECORD)","ab32f0c6-2239-afbb-c470-d2ef4e254db7":"TOKEN2 FIDO2 Security Key","adce0002-35bc-c60a-648b-0b25f1f05503":"Chrome on Mac","aeb6569c-f8fb-4950-ac60-24ca2bbe2e52":"HID Crescendo C2300","b267239b-954f-4041-a01b-ee4f33c145b6":"authenton1 - CTAP2.1","b50d5e0a-7f81-4959-9b12-f45407407503":"IDPrime 3940 FIDO","b5397666-4885-aa6b-cebf-e52262a439a2":"Chromium Browser","b6ede29c-3772-412c-8a78-539c1f4c62d2":"Feitian BioPass FIDO2 Plus Authenticator","b84e4048-15dc-4dd0-8640-f4f60813c8af":"NordPass","b92c3f9a-c014-4056-887f-140a2501163b":"Security Key by Yubico","b93fd961-f2e6-462f-b122-82002247de78":"Android Authenticator with SafetyNet Attestation","ba76a271-6eb6-4171-874d-b6428dbe3437":"ATKey.ProS","ba86dc56-635f-4141-aef6-00227b1b9af6":"TruU Windows Authenticator","bada5566-a7aa-401f-bd96-45619a55120d":"1Password","bbf4b6a7-679d-f6fc-c4f2-8ac0ddf9015a":"Excelsecu eSecu FIDO2 PRO Security Key","bc2fe499-0d8e-4ffe-96f3-94a82840cf8c":"OCTATCO EzQuant FIDO2 AUTHENTICATOR","be727034-574a-f799-5c76-0929e0430973":"Crayonic KeyVault K1 (USB-NFC-BLE FIDO2 Authenticator)","c1f9a0bc-1dd2-404a-b27f-8e29047a43fd":"YubiKey 5 FIPS Series with NFC","c5703116-972b-4851-a3e7-ae1259843399":"NEOWAVE Badgeo FIDO2","c5ef55ff-ad9a-4b9f-b580-adebafe026d0":"YubiKey 5 Series with Lightning","c80dbd9a-533f-4a17-b941-1a2f1c7cedff":"HID Crescendo C3000","ca4cff1b-5a81-4404-8194-59aabcf1660b":"IDPrime 3930 FIDO","ca87cb70-4c1b-4579-a8e8-4efdd7c007e0":"FIDO Alliance TruU Sample FIDO2 Authenticator","cb69481e-8ff7-4039-93ec-0a2729a154a8":"YubiKey 5 Series","cc45f64e-52a2-451b-831a-4edd8022a202":"ToothPic Passkey Provider","cd69adb5-3c7a-deb9-3177-6800ea6cb72a":"Thales PIN Android SDK","cdbdaea2-c415-5073-50f7-c04e968640b6":"Excelsecu eSecu FIDO2 Security Key","cfcb13a2-244f-4b36-9077-82b79d6a7de7":"USB/NFC Passcode Authenticator","d384db22-4d50-ebde-2eac-5765cf1e2a44":"Excelsecu eSecu FIDO2 Fingerprint Security Key","d41f5a69-b817-4144-a13c-9ebd6d9254d6":"ATKey.Card CTAP2.0","d548826e-79b4-db40-a3d8-11116f7e8349":"Bitwarden","d61d3b87-3e7c-4aea-9c50-441c371903ad":"KeyVault Secp256R1 FIDO2 CTAP2 Authenticator","d7a423ad-3e19-4492-9200-78137dccc136":"VivoKey Apex FIDO2","d821a7d4-e97c-4cb6-bd82-4237731fd4be":"Hyper FIDO Bio Security Key","d8522d9f-575b-4866-88a9-ba99fa02f35b":"YubiKey Bio Series","d91c5288-0ef0-49b7-b8ae-21ca0aa6b3f3":"KEY-ID FIDO2 Authenticator","d94a29d9-52dd-4247-9c2d-8b818b610389":"VeriMark Guard Fingerprint Key","da1fa263-8b25-42b6-a820-c0036f21ba7f":"ATKey.Card NFC","dd4ec289-e01d-41c9-bb89-70fa845d4bf2":"iCloud Keychain (Managed)","e1a96183-5016-4f24-b55b-e3ae23614cc6":"ATKey.Pro CTAP2.0","e416201b-afeb-41ca-a03d-2281c28322aa":"ATKey.Pro CTAP2.1","e77e3c64-05e3-428b-8824-0cbeb04b829d":"Security Key NFC by Yubico","e86addcd-7711-47e5-b42a-c18257b0bf61":"IDCore 3121 Fido","ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4":"Google Password Manager","eabb46cc-e241-80bf-ae9e-96fa6d2975cf":"TOKEN2 PIN Plus Security Key Series ","eb3b131e-59dc-536a-d176-cb7306da10f5":"ellipticSecure MIRkey USB Authenticator","ec31b4cc-2acc-4b8e-9c01-bade00ccbe26":"KeyXentic FIDO2 Secp256R1 FIDO2 CTAP2 Authenticator","ee041bce-25e5-4cdb-8f86-897fd6418464":"Feitian ePass FIDO2-NFC Authenticator","ee882879-721c-4913-9775-3dfcce97072a":"YubiKey 5 Series","efb96b10-a9ee-4b6c-a4a9-d32125ccd4a4":"Safenet eToken FIDO","f3809540-7f14-49c1-a8b3-8f813b225541":"Enpass","f4c63eff-d26c-4248-801c-3736c7eaa93a":"FIDO KeyPass S3","f56f58b3-d711-4afc-ba7d-6ac05f88cb19":"WinMagic FIDO Eazy - Phone","f7c558a0-f465-11e8-b568-0800200c9a66":"KONAI Secp256R1 FIDO2 Conformance Testing CTAP2 Authenticator","f8a011f3-8c0a-4d15-8006-17111f9edc7d":"Security Key by Yubico","fa2b99dc-9e39-4257-8f92-4a30d23c4118":"YubiKey 5 Series with NFC","fbefdf68-fe86-0106-213e-4d5fa24cbe2e":"Excelsecu eSecu FIDO2 NFC Security Key","fbfc3007-154e-4ecc-8c0b-6e020557d7bd":"iCloud Keychain","fcb1bcb4-f370-078c-6993-bc24d0ae3fbe":"Ledger Nano X FIDO2 Authenticator","fdb141b2-5d84-443e-8a35-4698c205a502":"KeePassXC","fec067a1-f1d0-4c5e-b4c0-cc3237475461":"KX701 SmartToken FIDO"};var W=new TextDecoder("utf-8");function S(e){return typeof e=="string"&&(e=o(e)),JSON.parse(W.decode(e))}function b(e){typeof e=="string"&&(e=o(e));let t=new DataView(e.slice(32,33)).getUint8(0);return{rpIdHash:$(e),flags:{userPresent:!!(t&1),userVerified:!!(t&4),backupEligibility:!!(t&8),backupState:!!(t&16),attestedData:!!(t&64),extensionsIncluded:!!(t&128)},signCount:new DataView(e.slice(33,37)).getUint32(0,!1),aaguid:G(e)}}function $(e){return n(e.slice(0,32))}function G(e){if(e.byteLength<53)return"00000000-0000-0000-0000-000000000000";let t=e.slice(37,53),a=C(t);return`${a.substring(0,8)}-${a.substring(8,12)}-${a.substring(12,16)}-${a.substring(16,20)}-${a.substring(20,32)}`}function E(e){switch(e){case-7:return"ES256";case-8:return"EdDSA";case-257:return"RS256";default:throw new Error(`Unknown algorithm code: ${e}`)}}function z(e){let t=b(e.response.authenticatorData);return N(e,t)}function N(e,t){let a=t.aaguid;return{authenticator:{aaguid:a,counter:t.signCount,icon_light:"https://webauthn.passwordless.id/authenticators/"+a+"-light.png",icon_dark:"https://webauthn.passwordless.id/authenticators/"+a+"-dark.png",name:p[a]??"Unknown"},credential:{id:e.id,publicKey:e.response.publicKey,algorithm:E(e.response.publicKeyAlgorithm),transports:e.response.transports},synced:t.flags.backupEligibility,user:e.user,userVerified:t.flags.userVerified}}function I(e,t){return{credentialId:e.id,userId:e.response.userHandle,counter:t.signCount,userVerified:t.flags.userVerified,authenticatorAttachment:e.authenticatorAttachment}}function j(e){let t=b(e.response.authenticatorData);return I(e,t)}function J(){let e=crypto.getRandomValues(new Uint8Array(18));return n(e)}async function X(e,t){if(typeof e=="function"){let a=e(t);return a instanceof Promise?await a:a}return e===t}async function m(e,t){return!await X(e,t)}async function _(e,t){let a=S(e.response.clientDataJSON),r=b(e.response.authenticatorData);if(!r.aaguid)throw new Error("Unexpected errror, no AAGUID.");if(a.type!=="webauthn.create")throw new Error(`Unexpected ClientData type: ${a.type}`);if(await m(t.origin,a.origin))throw new Error(`Unexpected ClientData origin: ${a.origin}`);if(await m(t.challenge,a.challenge))throw new Error(`Unexpected ClientData challenge: ${a.challenge}`);return l.toRegistrationInfo(e,r)}async function q(e,t,a){if(e.id!==t.id)throw new Error(`Credential ID mismatch: ${e.id} vs ${t.id}`);if(!await U({algorithm:t.algorithm,publicKey:t.publicKey,authenticatorData:e.response.authenticatorData,clientData:e.response.clientDataJSON,signature:e.response.signature,verbose:a.verbose}))throw new Error(`Invalid signature: ${e.response.signature}`);let i=S(e.response.clientDataJSON),c=b(e.response.authenticatorData);if(a.verbose&&(console.debug(i),console.debug(c)),i.type!=="webauthn.get")throw new Error(`Unexpected clientData type: ${i.type}`);if(await m(a.origin,i.origin))throw new Error(`Unexpected ClientData origin: ${i.origin}`);if(await m(a.challenge,i.challenge))throw new Error(`Unexpected ClientData challenge: ${i.challenge}`);let d=a.domain??new URL(i.origin).hostname,h=n(await A(f(d)));if(c.rpIdHash!==h)throw new Error(`Unexpected RpIdHash: ${c.rpIdHash} vs ${h}`);if(!c.flags.userPresent)throw new Error("Unexpected authenticator flags: missing userPresent");if(!c.flags.userVerified&&a.userVerified)throw new Error("Unexpected authenticator flags: missing userVerified");if(a.counter&&c.signCount<=a.counter)throw new Error(`Unexpected authenticator counter: ${c.signCount} (should be > ${a.counter})`);return I(e,c)}function T(e){switch(e){case"RS256":return{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"};case"ES256":return{name:"ECDSA",namedCurve:"P-256",hash:"SHA-256"};default:throw new Error(`Unknown or unsupported crypto algorithm: ${e}. Only 'RS256' and 'ES256' are supported.`)}}async function R(e,t){let a=T(e),r=o(t);return crypto.subtle.importKey("spki",r,a,!1,["verify"])}async function U({algorithm:e,publicKey:t,authenticatorData:a,clientData:r,signature:i,verbose:c}){let d=await R(e,t);c&&console.debug(d);let h=await A(o(r)),P=O(o(a),h);c&&(console.debug("Algorithm: "+e),console.debug("Public key: "+t),console.debug("Data: "+n(P)),console.debug("Signature: "+i));let D=o(i);e=="ES256"&&(D=Z(D));let x=T(e);return await crypto.subtle.verify(x,d,D,P)}function Z(e){let t=new Uint8Array(e),a=t[4]===0?5:4,r=a+32,i=t[r+2]===0?r+3:r+2,c=t.slice(a,r),d=t.slice(i);return new Uint8Array([...c,...d])}var Q={client:w,server:F,parsers:l,utils:u,authenticatorMetadata:p},se=Q;export{p as authenticatorMetadata,w as client,se as default,l as parsers,F as server,u as utils}; //# sourceMappingURL=webauthn.min.js.map diff --git a/docs/demos/js/webauthn.min.js.map b/docs/demos/js/webauthn.min.js.map index e467b6f..5b5ff99 100644 --- a/docs/demos/js/webauthn.min.js.map +++ b/docs/demos/js/webauthn.min.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../src/client.ts", "../../src/utils.ts", "../../src/server.ts", "../../src/parsers.ts", "../../src/authenticatorMetadata.ts", "../../src/index.ts"], - "sourcesContent": ["import { AuthenticateOptions, AuthenticationJSON, Base64URLString, CredentialDescriptor, ExtendedAuthenticatorTransport, PublicKeyCredentialHints, RegisterOptions, RegistrationJSON, User, WebAuthnCreateOptions, WebAuthnGetOptions } from './types.js'\nimport * as utils from './utils'\n\n/**\n * Returns whether passwordless authentication is available on this browser/platform or not.\n */\nexport function isAvailable(): boolean {\n return !!window.PublicKeyCredential\n}\n\n/**\n * Returns whether the device itself can be used as authenticator.\n */\nexport async function isLocalAuthenticator(): Promise {\n return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()\n}\n\n\n\n/**\n * Before \"hints\" were a thing, the \"authenticatorAttachment\" was the way to go.\n */\nfunction getAuthAttachment(hints?: PublicKeyCredentialHints[]): AuthenticatorAttachment | undefined {\n if (!hints || hints.length === 0)\n return undefined // The webauthn protocol considers `null` as invalid but `undefined` as \"both\"!\n\n if (hints.includes('client-device')) {\n if (hints.includes('security-key') || hints.includes('hybrid'))\n return undefined // both\n else\n return \"platform\";\n }\n return \"cross-platform\";\n}\n\n\n/**\n * For autocomplete / conditional mediation, the ongoing \"authentication\" must be aborted when triggering a registration.\n * It should also be aborted when triggering authentication another time.\n */\nlet ongoingAuth: AbortController | null = null;\n\n\n/**\n * Creates a cryptographic key pair, in order to register the public key for later passwordless authentication.\n *\n * @param {string|Object} [user] Username or user object (id, name, displayName)\n * @param {string} [challenge] A server-side randomly generated string.\n * @param {number} [timeout=60000] Number of milliseconds the user has to respond to the biometric/PIN check.\n * @param {'required'|'preferred'|'discouraged'} [userVerification='required'] Whether to prompt for biometric/PIN check or not.\n * @param {PublicKeyCredentialHints[]} [hints]: Can contain a list of \"client-device\", \"hybrid\" or \"security-key\"\n * @param {boolean} [attestation=false] If enabled, the device attestation and clientData will be provided as Base64url encoded binary data. Note that this is not available on some platforms.\n * @param {'discouraged'|'preferred'|'required'} [discoverable] A \"discoverable\" credential can be selected using `authenticate(...)` without providing credential IDs.\n * Instead, a native pop-up will appear for user selection.\n * This may have an impact on the \"passkeys\" user experience and syncing behavior of the key.\n */\nexport async function register(options: RegisterOptions): Promise {\n\n if (!options.challenge)\n throw new Error('\"challenge\" required')\n\n if (!options.user)\n throw new Error('\"user\" required')\n\n if (!utils.isBase64url(options.challenge))\n throw new Error('Provided challenge is not properly encoded in Base64url')\n\n const user: User = typeof (options.user) === 'string' ? { name: options.user } : options.user\n if (!user.id)\n user.id = crypto.randomUUID()\n\n const creationOptions: WebAuthnCreateOptions = {\n challenge: utils.parseBase64url(options.challenge),\n rp: {\n id: options.domain ?? window.location.hostname,\n name: options.domain ?? window.location.hostname\n },\n user: {\n id: utils.toBuffer(user.id),\n name: user.name,\n displayName: user.displayName ?? user.name,\n },\n hints: options.hints,\n pubKeyCredParams: [\n { alg: -7, type: \"public-key\" }, // ES256 (Webauthn's default algorithm)\n { alg: -257, type: \"public-key\" }, // RS256 (for older Windows Hello and others)\n ],\n timeout: options.timeout,\n authenticatorSelection: {\n userVerification: options.userVerification,\n authenticatorAttachment: getAuthAttachment(options.hints),\n residentKey: options.discoverable ?? 'preferred', // see https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#residentkey\n requireResidentKey: (options.discoverable === 'required') // mainly for backwards compatibility, see https://www.w3.org/TR/webauthn/#dictionary-authenticatorSelection\n },\n attestation: \"direct\"\n }\n\n console.debug(creationOptions)\n\n if (ongoingAuth != null)\n ongoingAuth.abort('Cancel ongoing authentication')\n ongoingAuth = new AbortController();\n\n const raw = await navigator.credentials.create({\n publicKey: creationOptions,\n signal: ongoingAuth?.signal\n }) as PublicKeyCredential\n const response = raw.response as AuthenticatorAttestationResponse\n\n ongoingAuth = null;\n\n console.debug(raw)\n\n if (raw.type != \"public-key\")\n throw \"Unexpected credential type!\";\n\n const publicKey = response.getPublicKey();\n if (!publicKey)\n throw \"Non-compliant browser or authenticator!\"\n\n // This should provide the same as `response.toJson()` which is sadly only available on FireFox\n const json: RegistrationJSON = {\n type: raw.type,\n id: raw.id,\n rawId: utils.toBase64url(raw.rawId), // Same as ID, but useful in tests\n authenticatorAttachment: raw.authenticatorAttachment as AuthenticatorAttachment,\n clientExtensionResults: raw.getClientExtensionResults(),\n response: {\n attestationObject: utils.toBase64url(response.attestationObject),\n authenticatorData: utils.toBase64url(response.getAuthenticatorData()),\n clientDataJSON: utils.toBase64url(response.clientDataJSON),\n publicKey: utils.toBase64url(publicKey),\n publicKeyAlgorithm: response.getPublicKeyAlgorithm(),\n transports: response.getTransports() as AuthenticatorTransport[],\n },\n user, // That's our own addition \n }\n return json\n}\n\nexport async function isAutocompleteAvailable() {\n return PublicKeyCredential.isConditionalMediationAvailable && PublicKeyCredential.isConditionalMediationAvailable();\n}\n\n/**\n * Signs a challenge using one of the provided credentials IDs in order to authenticate the user.\n *\n * @param {string[]} credentialIds The list of credential IDs that can be used for signing.\n * @param {string} challenge A server-side randomly generated string, the base64 encoded version will be signed.\n * @param {number} [timeout=60000] Number of milliseconds the user has to respond to the biometric/PIN check.\n * @param {'required'|'preferred'|'discouraged'} [userVerification='required'] Whether to prompt for biometric/PIN check or not.\n * @param {boolean} [conditional] Does not return directly, but only when the user has selected a credential in the input field with `autocomplete=\"username webauthn\"`\n */\nexport async function authenticate(options: AuthenticateOptions): Promise {\n if (!utils.isBase64url(options.challenge))\n throw new Error('Provided challenge is not properly encoded in Base64url')\n\n if (options.autocomplete && !(await isAutocompleteAvailable()))\n throw new Error('PAsskeys autocomplete with conditional mediation is not available in this browser.')\n\n let authOptions: WebAuthnGetOptions = {\n challenge: utils.parseBase64url(options.challenge),\n rpId: options.domain ?? window.location.hostname,\n allowCredentials: options.allowCredentials?.map(toPublicKeyCredentialDescriptor),\n hints: options.hints,\n userVerification: options.userVerification,\n timeout: options.timeout,\n }\n\n console.debug(authOptions)\n\n if (options.autocomplete) {\n if(ongoingAuth != null)\n ongoingAuth.abort('Cancel ongoing authentication')\n ongoingAuth = new AbortController();\n }\n \n const raw = await navigator.credentials.get({\n publicKey: authOptions,\n mediation: options.autocomplete ? 'conditional' : undefined,\n signal: ongoingAuth?.signal\n }) as PublicKeyCredential\n\n if (raw.type != \"public-key\")\n throw \"Unexpected credential type!\";\n\n ongoingAuth = null;\n\n console.debug(raw)\n\n const response = raw.response as AuthenticatorAssertionResponse\n\n // This should provide the same as `response.toJson()` which is sadly only available on FireFox\n const json: AuthenticationJSON = {\n clientExtensionResults: raw.getClientExtensionResults(),\n id: raw.id,\n rawId: utils.toBase64url(raw.rawId),\n type: raw.type,\n authenticatorAttachment: raw.authenticatorAttachment as AuthenticatorAttachment,\n response: {\n authenticatorData: utils.toBase64url(response.authenticatorData),\n clientDataJSON: utils.toBase64url(response.clientDataJSON),\n signature: utils.toBase64url(response.signature),\n userHandle: response.userHandle ? utils.toBase64url(response.userHandle) : undefined\n }\n }\n\n return json\n}\n\nfunction toPublicKeyCredentialDescriptor(cred: Base64URLString | CredentialDescriptor): PublicKeyCredentialDescriptor {\n if(typeof cred === 'string') {\n return {\n id: utils.parseBase64url(cred),\n type: 'public-key'\n }\n }\n else {\n return {\n id: utils.parseBase64url(cred.id),\n type: 'public-key',\n transports: cred.transports as AuthenticatorTransport[]\n }\n }\n}\n", "/********************************\n Encoding/Decoding Utils\n********************************/\n\nimport { Base64URLString } from \"./types\"\n\n\nexport function toBuffer(txt :string) :ArrayBuffer {\n return Uint8Array.from(txt, c => c.charCodeAt(0)).buffer\n}\n\nexport function parseBuffer(buffer :ArrayBuffer) :string {\n return String.fromCharCode(...new Uint8Array(buffer))\n}\n\n\nexport function isBase64url(txt :string) :boolean {\n return txt.match(/^[a-zA-Z0-9\\-_]+=*$/) !== null\n}\n\nexport function toBase64url(buffer :ArrayBuffer) :Base64URLString {\n const txt = btoa(parseBuffer(buffer)) // base64\n return txt.replaceAll('+', '-').replaceAll('/', '_')\n}\n\nexport function parseBase64url(txt :Base64URLString) :ArrayBuffer {\n txt = txt.replaceAll('-', '+').replaceAll('_', '/') // base64url -> base64\n return toBuffer(atob(txt))\n}\n\n\nexport async function sha256(buffer :ArrayBuffer) :Promise {\n return await crypto.subtle.digest('SHA-256', buffer)\n}\n\nexport function bufferToHex (buffer :ArrayBuffer) :string {\n return [...new Uint8Array (buffer)]\n .map (b => b.toString (16).padStart (2, \"0\"))\n .join (\"\");\n}\n\n\nexport function concatenateBuffers(buffer1 :ArrayBuffer, buffer2 :ArrayBuffer) {\n var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);\n tmp.set(new Uint8Array(buffer1), 0);\n tmp.set(new Uint8Array(buffer2), buffer1.byteLength);\n return tmp;\n };", "import { authenticatorMetadata, parsers } from \"./index\";\nimport { parseAuthenticator, parseClient, toAuthenticationInfo } from \"./parsers\";\nimport { AuthenticationJSON, NamedAlgo, RegistrationJSON, RegistrationInfo, AuthenticationInfo, Base64URLString, CollectedClientData, UserInfo, CredentialInfo, AuthenticatorInfo, AuthenticatorParsed } from \"./types\";\nimport * as utils from './utils'\n\n\nexport function randomChallenge() {\n const buffer = crypto.getRandomValues(new Uint8Array(18)); // > 128 bits, a multiple of 3 bytes to have base64 encoding without padding\n return utils.toBase64url(buffer);\n}\n\n\n\nasync function isValid(validator :any, value :any) :Promise {\n if(typeof validator === 'function') {\n const res = validator(value)\n if(res instanceof Promise)\n return await res\n else\n return res\n }\n // the validator can be a single value too\n return validator === value\n}\n\nasync function isNotValid(validator :any, value :any) :Promise {\n return !(await isValid(validator, value))\n}\n\ninterface RegistrationChecks {\n challenge: string | Function,\n origin: string | Function\n}\n\n\n\nexport async function verifyRegistration(registrationJson: RegistrationJSON, expected: RegistrationChecks): Promise {\n const client = parseClient(registrationJson.response.clientDataJSON)\n const authenticator = parseAuthenticator(registrationJson.response.authenticatorData);\n const aaguid = authenticator.aaguid;\n\n if(!aaguid) // should never happen, worst case should be a fallback to \"zeroed\" aaguid\n throw new Error(\"Unexpected errror, no AAGUID.\")\n\n if (client.type !== \"webauthn.create\")\n throw new Error(`Unexpected ClientData type: ${client.type}`)\n\n if (await isNotValid(expected.origin, client.origin))\n throw new Error(`Unexpected ClientData origin: ${client.origin}`)\n\n if (await isNotValid(expected.challenge, client.challenge))\n throw new Error(`Unexpected ClientData challenge: ${client.challenge}`)\n\n return parsers.toRegistrationInfo(registrationJson, authenticator)\n}\n\n\n\ninterface AuthenticationChecks {\n challenge: string | Function,\n origin: string | Function,\n userVerified: boolean,\n counter?: number, // Made optional according to https://github.com/passwordless-id/webauthn/issues/38\n domain ?:string, // Same as `rp.id`\n verbose?: boolean\n}\n\n\n\nexport async function verifyAuthentication(authenticationJson: AuthenticationJSON, credential: CredentialInfo, expected: AuthenticationChecks): Promise {\n if (authenticationJson.id !== credential.id)\n throw new Error(`Credential ID mismatch: ${authenticationJson.id} vs ${credential.id}`)\n\n const isValidSignature: boolean = await verifySignature({\n algorithm: credential.algorithm,\n publicKey: credential.publicKey,\n authenticatorData: authenticationJson.response.authenticatorData,\n clientData: authenticationJson.response.clientDataJSON,\n signature: authenticationJson.response.signature,\n verbose: expected.verbose\n })\n\n if(!isValidSignature)\n throw new Error(`Invalid signature: ${authenticationJson.response.signature}`)\n\n const client :CollectedClientData = parseClient(authenticationJson.response.clientDataJSON);\n const authenticator :AuthenticatorParsed = parseAuthenticator(authenticationJson.response.authenticatorData);\n\n if(expected.verbose) {\n console.debug(client)\n console.debug(authenticator)\n }\n \n if (client.type !== \"webauthn.get\")\n throw new Error(`Unexpected clientData type: ${client.type}`)\n\n if (await isNotValid(expected.origin, client.origin))\n throw new Error(`Unexpected ClientData origin: ${client.origin}`)\n\n if (await isNotValid(expected.challenge, client.challenge))\n throw new Error(`Unexpected ClientData challenge: ${client.challenge}`)\n\n // this only works because we consider `rp.origin` and `rp.id` to be the same during authentication/registration\n const rpId = expected.domain ?? new URL(client.origin).hostname\n const expectedRpIdHash = utils.toBase64url(await utils.sha256(utils.toBuffer(rpId)))\n if (authenticator.rpIdHash !== expectedRpIdHash)\n throw new Error(`Unexpected RpIdHash: ${authenticator.rpIdHash} vs ${expectedRpIdHash}`)\n\n if (!authenticator.flags.userPresent)\n throw new Error(`Unexpected authenticator flags: missing userPresent`)\n\n if (!authenticator.flags.userVerified && expected.userVerified)\n throw new Error(`Unexpected authenticator flags: missing userVerified`)\n\n if (expected.counter && authenticator.signCount <= expected.counter)\n throw new Error(`Unexpected authenticator counter: ${authenticator.signCount} (should be > ${expected.counter})`)\n\n return toAuthenticationInfo(authenticationJson, authenticator)\n}\n\n\n// https://w3c.github.io/webauthn/#sctn-public-key-easy\n// https://www.iana.org/assignments/cose/cose.xhtml#algorithms\n/*\nUser agents MUST be able to return a non-null value for getPublicKey() when the credential public key has a COSEAlgorithmIdentifier value of:\n\n-7 (ES256), where kty is 2 (with uncompressed points) and crv is 1 (P-256).\n\n-257 (RS256).\n\n-8 (EdDSA), where crv is 6 (Ed25519).\n*/\nfunction getAlgoParams(algorithm: NamedAlgo): any {\n switch (algorithm) {\n case 'RS256':\n return {\n name: 'RSASSA-PKCS1-v1_5',\n hash: 'SHA-256'\n };\n case 'ES256':\n return {\n name: 'ECDSA',\n namedCurve: 'P-256',\n hash: 'SHA-256',\n };\n // case 'EdDSA': Not supported by browsers\n default:\n throw new Error(`Unknown or unsupported crypto algorithm: ${algorithm}. Only 'RS256' and 'ES256' are supported.`)\n }\n}\n\ntype AlgoParams = AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm\n\nasync function parseCryptoKey(algoParams: AlgoParams, publicKey: string): Promise {\n const buffer = utils.parseBase64url(publicKey)\n return crypto.subtle.importKey('spki', buffer, algoParams, false, ['verify'])\n}\n\n\n\ntype VerifyParams = {\n algorithm: NamedAlgo,\n publicKey: Base64URLString,\n authenticatorData: Base64URLString,\n clientData: Base64URLString,\n signature: Base64URLString,\n verbose?: boolean, // Enables debug logs containing sensitive data like crypto keys\n}\n\n\n// https://w3c.github.io/webauthn/#sctn-verifying-assertion\n// https://w3c.github.io/webauthn/#sctn-signature-attestation-types\n/* Emphasis mine:\n\n6.5.6. Signature Formats for Packed Attestation, FIDO U2F Attestation, and **Assertion Signatures**\n\n[...] For COSEAlgorithmIdentifier -7 (ES256) [...] the sig value MUST be encoded as an ASN.1 [...]\n[...] For COSEAlgorithmIdentifier -257 (RS256) [...] The signature is not ASN.1 wrapped.\n[...] For COSEAlgorithmIdentifier -37 (PS256) [...] The signature is not ASN.1 wrapped.\n*/\n// see also https://gist.github.com/philholden/50120652bfe0498958fd5926694ba354\nexport async function verifySignature({ algorithm, publicKey, authenticatorData, clientData, signature, verbose }: VerifyParams): Promise {\n const algoParams = getAlgoParams(algorithm)\n let cryptoKey = await parseCryptoKey(algoParams, publicKey)\n\n if(verbose) {\n console.debug(cryptoKey)\n }\n\n let clientHash = await utils.sha256(utils.parseBase64url(clientData));\n\n // during \"login\", the authenticatorData is exactly 37 bytes\n let comboBuffer = utils.concatenateBuffers(utils.parseBase64url(authenticatorData), clientHash)\n\n if(verbose) {\n console.debug('Crypto Algo: ' + JSON.stringify(algoParams))\n console.debug('Public key: ' + publicKey)\n console.debug('Data: ' + utils.toBase64url(comboBuffer))\n console.debug('Signature: ' + signature)\n }\n\n // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify\n let signatureBuffer = utils.parseBase64url(signature)\n if(algorithm == 'ES256')\n signatureBuffer = convertASN1toRaw(signatureBuffer)\n\n const isValid = await crypto.subtle.verify(algoParams, cryptoKey, signatureBuffer, comboBuffer)\n\n return isValid\n}\n\nfunction convertASN1toRaw(signatureBuffer :ArrayBuffer) {\n // Convert signature from ASN.1 sequence to \"raw\" format\n const signature = new Uint8Array(signatureBuffer);\n const rStart = signature[4] === 0 ? 5 : 4;\n const rEnd = rStart + 32;\n const sStart = signature[rEnd + 2] === 0 ? rEnd + 3 : rEnd + 2;\n const r = signature.slice(rStart, rEnd);\n const s = signature.slice(sStart);\n return new Uint8Array([...r, ...s]);\n}", "import * as utils from './utils'\nimport { Base64URLString, CollectedClientData, NamedAlgo, AuthenticatorParsed, RegistrationJSON, RegistrationInfo, UserInfo, AuthenticationInfo, AuthenticationJSON } from './types'\nimport { authenticatorMetadata } from './authenticatorMetadata'\n\nconst utf8Decoder = new TextDecoder('utf-8')\n\n\ninterface ClientInfo {\n type: \"webauthn.create\" | \"webauthn.get\"\n challenge: string\n origin: string\n crossOrigin: boolean\n tokenBindingId?: {\n id: string\n status: string\n }\n extensions?: any\n}\n\n \nexport function parseClient(data :Base64URLString|ArrayBuffer) :CollectedClientData {\n if(typeof data == 'string')\n data = utils.parseBase64url(data)\n return JSON.parse(utf8Decoder.decode(data))\n}\n\n\nexport function parseAuthenticator(authData :Base64URLString|ArrayBuffer) :AuthenticatorParsed {\n if(typeof authData == 'string')\n authData = utils.parseBase64url(authData)\n \n //console.debug(authData)\n let flags = new DataView(authData.slice(32,33)).getUint8(0)\n //console.debug(flags)\n\n // https://w3c.github.io/webauthn/#sctn-authenticator-data\n return {\n rpIdHash: extractRpIdHash(authData),\n flags: {\n userPresent: !!(flags & 1),\n //reserved1: !!(flags & 2),\n userVerified: !!(flags & 4),\n backupEligibility: !!(flags & 8),\n backupState: !!(flags & 16),\n //reserved2: !!(flags & 32),\n attestedData: !!(flags & 64),\n extensionsIncluded: !!(flags & 128)\n },\n signCount: new DataView(authData.slice(33,37)).getUint32(0, false), // Big-Endian!\n aaguid: extractAaguid(authData),\n //credentialId: extractCredentialId() \n }\n}\n\nfunction extractRpIdHash(authData :ArrayBuffer) :Base64URLString {\n return utils.toBase64url(authData.slice(0,32))\n}\n\n/**\n * Returns the AAGUID in the format \"00000000-0000-0000-0000-000000000000\"\n */\nfunction extractAaguid(authData :ArrayBuffer) :string {\n if(authData.byteLength < 53)\n return \"00000000-0000-0000-0000-000000000000\"\n const buffer = authData.slice(37, 53) // 16 byte\n const hex = utils.bufferToHex(buffer)\n const aaguid :string = `${hex.substring(0,8)}-${hex.substring(8,12)}-${hex.substring(12,16)}-${hex.substring(16,20)}-${hex.substring(20,32)}`\n return aaguid // example: \"d41f5a69-b817-4144-a13c-9ebd6d9254d6\"\n}\n\n\n\nexport function getAlgoName(num :COSEAlgorithmIdentifier) :NamedAlgo {\n switch(num) {\n case -7: return \"ES256\"\n case -8: return \"EdDSA\"\n case -257: return \"RS256\"\n default: throw new Error(`Unknown algorithm code: ${num}`)\n }\n}\n\n\nexport function parseRegistration(registrationJson :RegistrationJSON) :RegistrationInfo {\n const authenticator = parseAuthenticator(registrationJson.response.authenticatorData);\n return toRegistrationInfo(registrationJson, authenticator);\n}\n\nexport function toRegistrationInfo(registrationJson :RegistrationJSON, authenticator :AuthenticatorParsed) :RegistrationInfo {\n const aaguid = authenticator.aaguid\n return {\n authenticator: {\n aaguid,\n counter: authenticator.signCount,\n icon_light: 'https://webauthn.passwordless.id/authenticators/' + aaguid + '-light.png',\n icon_dark: 'https://webauthn.passwordless.id/authenticators/' + aaguid + '-dark.png',\n name: authenticatorMetadata[aaguid] ?? 'Unknown',\n },\n credential: {\n id: registrationJson.id,\n publicKey: registrationJson.response.publicKey,\n algorithm: getAlgoName(registrationJson.response.publicKeyAlgorithm),\n transports: registrationJson.response.transports\n },\n synced: authenticator.flags.backupEligibility,\n user: registrationJson.user as UserInfo, // That's specific to this library\n userVerified: authenticator.flags.userVerified,\n }\n}\n\nexport function toAuthenticationInfo(authenticationJson :AuthenticationJSON, authenticator :AuthenticatorParsed) :AuthenticationInfo {\n return {\n credentialId: authenticationJson.id,\n userId: authenticationJson.response.userHandle,\n counter: authenticator.signCount,\n userVerified: authenticator.flags.userVerified,\n authenticatorAttachment: authenticationJson.authenticatorAttachment\n }\n}\n\n\nexport function parseAuthentication(authenticationJson :AuthenticationJSON) :AuthenticationInfo {\n const authenticator = parseAuthenticator(authenticationJson.response.authenticatorData);\n return toAuthenticationInfo(authenticationJson, authenticator);\n}\n", "/**\n * The source comes from\n * \"official\" https://mds.fidoalliance.org/\n * and the\n * \"community-driven\" https://github.com/passkeydeveloper/passkey-authenticator-aaguids\n * combined together.\n */\nexport const authenticatorMetadata :Record = {\n\t\"00000000-0000-0000-0000-000000000000\": \"Unknown authenticator\",\n\t\"0076631b-d4a0-427f-5773-0ec71c9e0279\": \"HYPR FIDO2 Authenticator\",\n\t\"07a9f89c-6407-4594-9d56-621d5f1e358b\": \"NXP Semiconductros FIDO2 Conformance Testing CTAP2 Authenticator\",\n\t\"08987058-cadc-4b81-b6e1-30de50dcbe96\": \"Windows Hello\",\n\t\"092277e5-8437-46b5-b911-ea64b294acb7\": \"Taglio CTAP2.1 CS\",\n\t\"09591fc6-9811-48f7-8f57-b9f23df6413f\": \"Pone Biometrics OFFPAD Authenticator\",\n\t\"0acf3011-bc60-f375-fb53-6f05f43154e0\": \"Nymi FIDO2 Authenticator\",\n\t\"0bb43545-fd2c-4185-87dd-feb0b2916ace\": \"Security Key NFC by Yubico - Enterprise Edition\",\n\t\"0d9b2e56-566b-c393-2940-f821b7f15d6d\": \"Excelsecu eSecu FIDO2 Pro Security Key\",\n\t\"0ea242b4-43c4-4a1b-8b17-dd6d0b6baec6\": \"Keeper\",\n\t\"1105e4ed-af1d-02ff-ffff-ffffffffffff\": \"Egomet FIDO2 Authenticator for Android\",\n\t\"12ded745-4bed-47d4-abaa-e713f51d6393\": \"Feitian AllinOne FIDO2 Authenticator\",\n\t\"149a2021-8ef6-4133-96b8-81f8d5b7f1f5\": \"Security Key by Yubico with NFC\",\n\t\"17290f1e-c212-34d0-1423-365d729f09d9\": \"Thales PIN iOS SDK\",\n\t\"175cd298-83d2-4a26-b637-313c07a6434e\": \"Chunghwa Telecom FIDO2 Smart Card Authenticator\",\n\t\"19083c3d-8383-4b18-bc03-8f1c9ab2fd1b\": \"YubiKey 5 Series\",\n\t\"1c086528-58d5-f211-823c-356786e36140\": \"Atos CardOS FIDO2\",\n\t\"20f0be98-9af9-986a-4b42-8eca4acb28e4\": \"Excelsecu eSecu FIDO2 Fingerprint Security Key\",\n\t\"2194b428-9397-4046-8f39-007a1605a482\": \"IDPrime 931 Fido\",\n\t\"234cd403-35a2-4cc2-8015-77ea280c77f5\": \"Feitian ePass FIDO2-NFC Series (CTAP2.1, CTAP2.0, U2F)\",\n\t\"23786452-f02d-4344-87ed-aaf703726881\": \"SafeNet eToken Fusion CC\",\n\t\"2772ce93-eb4b-4090-8b73-330f48477d73\": \"Security Key NFC by Yubico - Enterprise Edition Preview\",\n\t\"2c0df832-92de-4be1-8412-88a8f074df4a\": \"Feitian FIDO Smart Card\",\n\t\"2d3bec26-15ee-4f5d-88b2-53622490270b\": \"HID Crescendo Key V2\",\n\t\"2fc0579f-8113-47ea-b116-bb5a8db9202a\": \"YubiKey 5 Series with NFC\",\n\t\"2ffd6452-01da-471f-821b-ea4bf6c8676a\": \"IDPrime 941 Fido\",\n\t\"30b5035e-d297-4fc1-b00b-addc96ba6a97\": \"OneSpan FIDO Touch\",\n\t\"30b5035e-d297-4ff1-b00b-addc96ba6a98\": \"OneSpan DIGIPASS FX1 BIO\",\n\t\"3124e301-f14e-4e38-876d-fbeeb090e7bf\": \"YubiKey 5 Series with Lightning Preview\",\n\t\"31c3f7ff-bf15-4327-83ec-9336abcbcd34\": \"WinMagic FIDO Eazy - Software\",\n\t\"341e4da9-3c2e-8103-5a9f-aad887135200\": \"Ledger Nano S FIDO2 Authenticator\",\n\t\"34f5766d-1536-4a24-9033-0e294e510fb0\": \"YubiKey 5 Series with NFC Preview\",\n\t\"361a3082-0278-4583-a16f-72a527f973e4\": \"eWBM eFA500 FIDO2 Authenticator\",\n\t\"3789da91-f943-46bc-95c3-50ea2012f03a\": \"NEOWAVE Winkeo FIDO2\",\n\t\"39a5647e-1853-446c-a1f6-a79bae9f5bc7\": \"IDmelon\",\n\t\"3b1adb99-0dfe-46fd-90b8-7f7614a4de2a\": \"GoTrust Idem Key FIDO2 Authenticator\",\n\t\"3e078ffd-4c54-4586-8baa-a77da113aec5\": \"Hideez Key 3 FIDO2\",\n\t\"3e22415d-7fdf-4ea4-8a0c-dd60c4249b9d\": \"Feitian iePass FIDO Authenticator\",\n\t\"3f59672f-20aa-4afe-b6f4-7e5e916b6d98\": \"Arculus FIDO 2.1 Key Card [P71]\",\n\t\"42b4fb4a-2866-43b2-9bf7-6c6669c2e5d3\": \"Google Titan Security Key v2\",\n\t\"454e5346-4944-4ffd-6c93-8e9267193e9a\": \"Ensurity ThinC\",\n\t\"454e5346-4944-4ffd-6c93-8e9267193e9b\": \"Ensurity AUTH BioPro\",\n\t\"47ab2fb4-66ac-4184-9ae1-86be814012d5\": \"Security Key NFC by Yubico - Enterprise Edition\",\n\t\"4b3f8944-d4f2-4d21-bb19-764a986ec160\": \"KeyXentic FIDO2 Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"4c0cf95d-2f40-43b5-ba42-4c83a11c04ba\": \"Feitian BioPass FIDO2 Pro Authenticator\",\n\t\"4c50ff10-1057-4fc6-b8ed-43a529530c3c\": \"ImproveID Authenticator\",\n\t\"4d41190c-7beb-4a84-8018-adf265a6352d\": \"Thales IDPrime FIDO Bio\",\n\t\"4e768f2c-5fab-48b3-b300-220eb487752b\": \"Hideez Key 4 FIDO2 SDK\",\n\t\"504d7149-4e4c-3841-4555-55445a677357\": \"WiSECURE AuthTron USB FIDO2 Authenticator\",\n\t\"50726f74-6f6e-5061-7373-50726f746f6e\": \"Proton Pass\",\n\t\"50a45b0c-80e7-f944-bf29-f552bfa2e048\": \"ACS FIDO Authenticator\",\n\t\"516d3969-5a57-5651-5958-4e7a49434167\": \"SmartDisplayer BobeePass FIDO2 Authenticator\",\n\t\"531126d6-e717-415c-9320-3d9aa6981239\": \"Dashlane\",\n\t\"53414d53-554e-4700-0000-000000000000\": \"Samsung Pass\",\n\t\"5343502d-5343-5343-6172-644649444f32\": \"ESS Smart Card Inc. Authenticator\",\n\t\"54d9fee8-e621-4291-8b18-7157b99c5bec\": \"HID Crescendo Enabled\",\n\t\"5626bed4-e756-430b-a7ff-ca78c8b12738\": \"VALMIDO PRO FIDO\",\n\t\"58b44d0b-0a7c-f33a-fd48-f7153c871352\": \"Ledger Nano S Plus FIDO2 Authenticator\",\n\t\"5b0e46ba-db02-44ac-b979-ca9b84f5e335\": \"YubiKey 5 FIPS Series with Lightning Preview\",\n\t\"5ca1ab1e-1337-fa57-f1d0-a117e71ca702\": \"Allthenticator App: roaming BLE FIDO2 Allthenticator for Windows, Mac, Linux, and Allthenticate door readers\",\n\t\"5d629218-d3a5-11ed-afa1-0242ac120002\": \"Swissbit iShield Key Pro\",\n\t\"5fdb81b8-53f0-4967-a881-f5ec26fe4d18\": \"VinCSS FIDO2 Authenticator\",\n\t\"6002f033-3c07-ce3e-d0f7-0ffe5ed42543\": \"Excelsecu eSecu FIDO2 Fingerprint Key\",\n\t\"6028b017-b1d4-4c02-b4b3-afcdafc96bb2\": \"Windows Hello\",\n\t\"61250591-b2bc-4456-b719-0b17be90bb30\": \"eWBM eFPA FIDO2 Authenticator\",\n\t\"62e54e98-c209-4df3-b692-de71bb6a8528\": \"YubiKey 5 FIPS Series with NFC Preview\",\n\t\"664d9f67-84a2-412a-9ff7-b4f7d8ee6d05\": \"OpenSK authenticator\",\n\t\"66a0ccb3-bd6a-191f-ee06-e375c50b9846\": \"Thales Bio iOS SDK\",\n\t\"692db549-7ae5-44d5-a1e5-dd20a493b723\": \"HID Crescendo Key\",\n\t\"69700f79-d1fb-472e-bd9b-a3a3b9a9eda0\": \"Pone Biometrics OFFPAD Authenticator\",\n\t\"6d44ba9b-f6ec-2e49-b930-0c8fe920cb73\": \"Security Key by Yubico with NFC\",\n\t\"6dae43be-af9c-417b-8b9f-1b611168ec60\": \"Dapple Authenticator from Dapple Security Inc.\",\n\t\"73402251-f2a8-4f03-873e-3cb6db604b03\": \"uTrust FIDO2 Security Key\",\n\t\"73bb0cd4-e502-49b8-9c6f-b59445bf720b\": \"YubiKey 5 FIPS Series\",\n\t\"74820b05-a6c9-40f9-8fb0-9f86aca93998\": \"SafeNet eToken Fusion\",\n\t\"760eda36-00aa-4d29-855b-4012a182cdeb\": \"Security Key NFC by Yubico Preview\",\n\t\"77010bd7-212a-4fc9-b236-d2ca5e9d4084\": \"Feitian BioPass FIDO2 Authenticator\",\n\t\"771b48fd-d3d4-4f74-9232-fc157ab0507a\": \"Edge on Mac\",\n\t\"7d1351a6-e097-4852-b8bf-c9ac5c9ce4a3\": \"YubiKey Bio Series - Multi-protocol Edition\",\n\t\"7d2afadd-bf6b-44a2-a66b-e831fceb8eff\": \"Taglio CTAP2.1 EP\",\n\t\"7e3f3d30-3557-4442-bdae-139312178b39\": \"RSA DS100\",\n\t\"820d89ed-d65a-409e-85cb-f73f0578f82a\": \"IDmelon iOS Authenticator\",\n\t\"833b721a-ff5f-4d00-bb2e-bdda3ec01e29\": \"Feitian ePass FIDO2 Authenticator\",\n\t\"83c47309-aabb-4108-8470-8be838b573cb\": \"YubiKey Bio Series (Enterprise Profile)\",\n\t\"85203421-48f9-4355-9bc8-8a53846e5083\": \"YubiKey 5 FIPS Series with Lightning\",\n\t\"87dbc5a1-4c94-4dc8-8a47-97d800fd1f3c\": \"eWBM eFA320 FIDO2 Authenticator\",\n\t\"8836336a-f590-0921-301d-46427531eee6\": \"Thales Bio Android SDK\",\n\t\"8876631b-d4a0-427f-5773-0ec71c9e0279\": \"Solo Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"88bbd2f0-342a-42e7-9729-dd158be5407a\": \"Precision InnaIT Key FIDO 2 Level 2 certified\",\n\t\"891494da-2c90-4d31-a9cd-4eab0aed1309\": \"S\u00E9same\",\n\t\"8976631b-d4a0-427f-5773-0ec71c9e0279\": \"Solo Tap Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"89b19028-256b-4025-8872-255358d950e4\": \"Sentry Enterprises CTAP2 Authenticator\",\n\t\"8c97a730-3f7b-41a6-87d6-1e9b62bda6f0\": \"FT-JCOS FIDO Fingerprint Card\",\n\t\"8d1b1fcb-3c76-49a9-9129-5515b346aa02\": \"IDEMIA ID-ONE Card\",\n\t\"91ad6b93-264b-4987-8737-3a690cad6917\": \"Token Ring FIDO2 Authenticator\",\n\t\"931327dd-c89b-406c-a81e-ed7058ef36c6\": \"Swissbit iShield Key FIDO2\",\n\t\"95442b2e-f15e-4def-b270-efb106facb4e\": \"eWBM eFA310 FIDO2 Authenticator\",\n\t\"95e4d58c-056e-4a65-866d-f5a69659e880\": \"TruU Windows Authenticator\",\n\t\"970c8d9c-19d2-46af-aa32-3f448db49e35\": \"WinMagic FIDO Eazy - TPM\",\n\t\"973446ca-e21c-9a9b-99f5-9b985a67af0f\": \"ACS FIDO Authenticator Card\",\n\t\"9876631b-d4a0-427f-5773-0ec71c9e0279\": \"Somu Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"998f358b-2dd2-4cbe-a43a-e8107438dfb3\": \"OnlyKey Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"99bf4610-ec26-4252-b31f-7380ccd59db5\": \"ZTPass Card\",\n\t\"9c835346-796b-4c27-8898-d6032f515cc5\": \"Cryptnox FIDO2\",\n\t\"9d3df6ba-282f-11ed-a261-0242ac120002\": \"Arculus FIDO2/U2F Key Card\",\n\t\"9ddd1817-af5a-4672-a2b9-3e3dd95000a9\": \"Windows Hello\",\n\t\"9f0d8150-baa5-4c00-9299-ad62c8bb4e87\": \"GoTrust Idem Card FIDO2 Authenticator\",\n\t\"9f77e279-a6e2-4d58-b700-31e5943c6a98\": \"Hyper FIDO Pro\",\n\t\"a02167b9-ae71-4ac7-9a07-06432ebb6f1c\": \"YubiKey 5 Series with Lightning\",\n\t\"a1f52be5-dfab-4364-b51c-2bd496b14a56\": \"OCTATCO EzFinger2 FIDO2 AUTHENTICATOR\",\n\t\"a25342c0-3cdc-4414-8e46-f4807fca511c\": \"YubiKey 5 Series with NFC\",\n\t\"a3975549-b191-fd67-b8fb-017e2917fdb3\": \"Excelsecu eSecu FIDO2 NFC Security Key\",\n\t\"a4e9fc6d-4cbe-4758-b8ba-37598bb5bbaa\": \"Security Key NFC by Yubico\",\n\t\"ab32f0c6-2239-afbb-c470-d2ef4e254db6\": \"TEST (DUMMY RECORD)\",\n\t\"ab32f0c6-2239-afbb-c470-d2ef4e254db7\": \"TOKEN2 FIDO2 Security Key\",\n\t\"adce0002-35bc-c60a-648b-0b25f1f05503\": \"Chrome on Mac\",\n\t\"aeb6569c-f8fb-4950-ac60-24ca2bbe2e52\": \"HID Crescendo C2300\",\n\t\"b267239b-954f-4041-a01b-ee4f33c145b6\": \"authenton1 - CTAP2.1\",\n\t\"b50d5e0a-7f81-4959-9b12-f45407407503\": \"IDPrime 3940 FIDO\",\n\t\"b5397666-4885-aa6b-cebf-e52262a439a2\": \"Chromium Browser\",\n\t\"b6ede29c-3772-412c-8a78-539c1f4c62d2\": \"Feitian BioPass FIDO2 Plus Authenticator\",\n\t\"b84e4048-15dc-4dd0-8640-f4f60813c8af\": \"NordPass\",\n\t\"b92c3f9a-c014-4056-887f-140a2501163b\": \"Security Key by Yubico\",\n\t\"b93fd961-f2e6-462f-b122-82002247de78\": \"Android Authenticator with SafetyNet Attestation\",\n\t\"ba76a271-6eb6-4171-874d-b6428dbe3437\": \"ATKey.ProS\",\n\t\"ba86dc56-635f-4141-aef6-00227b1b9af6\": \"TruU Windows Authenticator\",\n\t\"bada5566-a7aa-401f-bd96-45619a55120d\": \"1Password\",\n\t\"bbf4b6a7-679d-f6fc-c4f2-8ac0ddf9015a\": \"Excelsecu eSecu FIDO2 PRO Security Key\",\n\t\"bc2fe499-0d8e-4ffe-96f3-94a82840cf8c\": \"OCTATCO EzQuant FIDO2 AUTHENTICATOR\",\n\t\"be727034-574a-f799-5c76-0929e0430973\": \"Crayonic KeyVault K1 (USB-NFC-BLE FIDO2 Authenticator)\",\n\t\"c1f9a0bc-1dd2-404a-b27f-8e29047a43fd\": \"YubiKey 5 FIPS Series with NFC\",\n\t\"c5703116-972b-4851-a3e7-ae1259843399\": \"NEOWAVE Badgeo FIDO2\",\n\t\"c5ef55ff-ad9a-4b9f-b580-adebafe026d0\": \"YubiKey 5 Series with Lightning\",\n\t\"c80dbd9a-533f-4a17-b941-1a2f1c7cedff\": \"HID Crescendo C3000\",\n\t\"ca4cff1b-5a81-4404-8194-59aabcf1660b\": \"IDPrime 3930 FIDO\",\n\t\"ca87cb70-4c1b-4579-a8e8-4efdd7c007e0\": \"FIDO Alliance TruU Sample FIDO2 Authenticator\",\n\t\"cb69481e-8ff7-4039-93ec-0a2729a154a8\": \"YubiKey 5 Series\",\n\t\"cc45f64e-52a2-451b-831a-4edd8022a202\": \"ToothPic Passkey Provider\",\n\t\"cd69adb5-3c7a-deb9-3177-6800ea6cb72a\": \"Thales PIN Android SDK\",\n\t\"cdbdaea2-c415-5073-50f7-c04e968640b6\": \"Excelsecu eSecu FIDO2 Security Key\",\n\t\"cfcb13a2-244f-4b36-9077-82b79d6a7de7\": \"USB/NFC Passcode Authenticator\",\n\t\"d384db22-4d50-ebde-2eac-5765cf1e2a44\": \"Excelsecu eSecu FIDO2 Fingerprint Security Key\",\n\t\"d41f5a69-b817-4144-a13c-9ebd6d9254d6\": \"ATKey.Card CTAP2.0\",\n\t\"d548826e-79b4-db40-a3d8-11116f7e8349\": \"Bitwarden\",\n\t\"d61d3b87-3e7c-4aea-9c50-441c371903ad\": \"KeyVault Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"d7a423ad-3e19-4492-9200-78137dccc136\": \"VivoKey Apex FIDO2\",\n\t\"d821a7d4-e97c-4cb6-bd82-4237731fd4be\": \"Hyper FIDO Bio Security Key\",\n\t\"d8522d9f-575b-4866-88a9-ba99fa02f35b\": \"YubiKey Bio Series\",\n\t\"d91c5288-0ef0-49b7-b8ae-21ca0aa6b3f3\": \"KEY-ID FIDO2 Authenticator\",\n\t\"d94a29d9-52dd-4247-9c2d-8b818b610389\": \"VeriMark Guard Fingerprint Key\",\n\t\"da1fa263-8b25-42b6-a820-c0036f21ba7f\": \"ATKey.Card NFC\",\n\t\"dd4ec289-e01d-41c9-bb89-70fa845d4bf2\": \"iCloud Keychain (Managed)\",\n\t\"e1a96183-5016-4f24-b55b-e3ae23614cc6\": \"ATKey.Pro CTAP2.0\",\n\t\"e416201b-afeb-41ca-a03d-2281c28322aa\": \"ATKey.Pro CTAP2.1\",\n\t\"e77e3c64-05e3-428b-8824-0cbeb04b829d\": \"Security Key NFC by Yubico\",\n\t\"e86addcd-7711-47e5-b42a-c18257b0bf61\": \"IDCore 3121 Fido\",\n\t\"ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4\": \"Google Password Manager\",\n\t\"eabb46cc-e241-80bf-ae9e-96fa6d2975cf\": \"TOKEN2 PIN Plus Security Key Series \",\n\t\"eb3b131e-59dc-536a-d176-cb7306da10f5\": \"ellipticSecure MIRkey USB Authenticator\",\n\t\"ec31b4cc-2acc-4b8e-9c01-bade00ccbe26\": \"KeyXentic FIDO2 Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"ee041bce-25e5-4cdb-8f86-897fd6418464\": \"Feitian ePass FIDO2-NFC Authenticator\",\n\t\"ee882879-721c-4913-9775-3dfcce97072a\": \"YubiKey 5 Series\",\n\t\"efb96b10-a9ee-4b6c-a4a9-d32125ccd4a4\": \"Safenet eToken FIDO\",\n\t\"f3809540-7f14-49c1-a8b3-8f813b225541\": \"Enpass\",\n\t\"f4c63eff-d26c-4248-801c-3736c7eaa93a\": \"FIDO KeyPass S3\",\n\t\"f56f58b3-d711-4afc-ba7d-6ac05f88cb19\": \"WinMagic FIDO Eazy - Phone\",\n\t\"f7c558a0-f465-11e8-b568-0800200c9a66\": \"KONAI Secp256R1 FIDO2 Conformance Testing CTAP2 Authenticator\",\n\t\"f8a011f3-8c0a-4d15-8006-17111f9edc7d\": \"Security Key by Yubico\",\n\t\"fa2b99dc-9e39-4257-8f92-4a30d23c4118\": \"YubiKey 5 Series with NFC\",\n\t\"fbefdf68-fe86-0106-213e-4d5fa24cbe2e\": \"Excelsecu eSecu FIDO2 NFC Security Key\",\n\t\"fbfc3007-154e-4ecc-8c0b-6e020557d7bd\": \"iCloud Keychain\",\n\t\"fcb1bcb4-f370-078c-6993-bc24d0ae3fbe\": \"Ledger Nano X FIDO2 Authenticator\",\n\t\"fdb141b2-5d84-443e-8a35-4698c205a502\": \"KeePassXC\",\n\t\"fec067a1-f1d0-4c5e-b4c0-cc3237475461\": \"KX701 SmartToken FIDO\",\n}", "import * as client from './client';\nimport * as server from './server';\nimport * as parsers from './parsers';\nimport * as utils from './utils';\nimport { authenticatorMetadata } from './authenticatorMetadata'\n\nexport { client, server, parsers, utils, authenticatorMetadata }\n\nconst webauthn = { client, server, parsers, utils, authenticatorMetadata }\nexport default webauthn\n"], - "mappings": "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", - "names": ["client_exports", "__export", "authenticate", "isAutocompleteAvailable", "isAvailable", "isLocalAuthenticator", "register", "utils_exports", "__export", "bufferToHex", "concatenateBuffers", "isBase64url", "parseBase64url", "parseBuffer", "sha256", "toBase64url", "toBuffer", "txt", "c", "buffer", "b", "buffer1", "buffer2", "tmp", "isAvailable", "isLocalAuthenticator", "getAuthAttachment", "hints", "ongoingAuth", "register", "options", "isBase64url", "user", "creationOptions", "parseBase64url", "toBuffer", "raw", "response", "publicKey", "toBase64url", "isAutocompleteAvailable", "authenticate", "authOptions", "toPublicKeyCredentialDescriptor", "cred", "server_exports", "__export", "randomChallenge", "verifyAuthentication", "verifyRegistration", "verifySignature", "parsers_exports", "__export", "getAlgoName", "parseAuthentication", "parseAuthenticator", "parseClient", "parseRegistration", "toAuthenticationInfo", "toRegistrationInfo", "authenticatorMetadata", "utf8Decoder", "parseClient", "data", "parseBase64url", "parseAuthenticator", "authData", "flags", "extractRpIdHash", "extractAaguid", "toBase64url", "buffer", "hex", "bufferToHex", "getAlgoName", "num", "parseRegistration", "registrationJson", "authenticator", "toRegistrationInfo", "aaguid", "authenticatorMetadata", "toAuthenticationInfo", "authenticationJson", "parseAuthentication", "randomChallenge", "buffer", "toBase64url", "isValid", "validator", "value", "res", "isNotValid", "verifyRegistration", "registrationJson", "expected", "client", "parseClient", "authenticator", "parseAuthenticator", "parsers_exports", "verifyAuthentication", "authenticationJson", "credential", "verifySignature", "rpId", "expectedRpIdHash", "sha256", "toBuffer", "toAuthenticationInfo", "getAlgoParams", "algorithm", "parseCryptoKey", "algoParams", "publicKey", "parseBase64url", "authenticatorData", "clientData", "signature", "verbose", "cryptoKey", "clientHash", "comboBuffer", "concatenateBuffers", "signatureBuffer", "convertASN1toRaw", "rStart", "rEnd", "sStart", "r", "s", "webauthn", "client_exports", "server_exports", "parsers_exports", "utils_exports", "authenticatorMetadata", "src_default"] + "sourcesContent": ["import { AuthenticateOptions, AuthenticationJSON, Base64URLString, CredentialDescriptor, ExtendedAuthenticatorTransport, PublicKeyCredentialHints, RegisterOptions, RegistrationJSON, User, WebAuthnCreateOptions, WebAuthnGetOptions } from './types.js'\nimport * as utils from './utils'\n\n/**\n * Returns whether passwordless authentication is available on this browser/platform or not.\n */\nexport function isAvailable(): boolean {\n return !!window.PublicKeyCredential\n}\n\n/**\n * Returns whether the device itself can be used as authenticator.\n */\nexport async function isLocalAuthenticator(): Promise {\n return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()\n}\n\n\n\n/**\n * Before \"hints\" were a thing, the \"authenticatorAttachment\" was the way to go.\n */\nfunction getAuthAttachment(hints?: PublicKeyCredentialHints[]): AuthenticatorAttachment | undefined {\n if (!hints || hints.length === 0)\n return undefined // The webauthn protocol considers `null` as invalid but `undefined` as \"both\"!\n\n if (hints.includes('client-device')) {\n if (hints.includes('security-key') || hints.includes('hybrid'))\n return undefined // both\n else\n return \"platform\";\n }\n return \"cross-platform\";\n}\n\n\n/**\n * For autocomplete / conditional mediation, the ongoing \"authentication\" must be aborted when triggering a registration.\n * It should also be aborted when triggering authentication another time.\n */\nlet ongoingAuth: AbortController | null = null;\n\n\n/**\n * Creates a cryptographic key pair, in order to register the public key for later passwordless authentication.\n *\n * @param {string|Object} [user] Username or user object (id, name, displayName)\n * @param {string} [challenge] A server-side randomly generated string.\n * @param {number} [timeout=60000] Number of milliseconds the user has to respond to the biometric/PIN check.\n * @param {'required'|'preferred'|'discouraged'} [userVerification='required'] Whether to prompt for biometric/PIN check or not.\n * @param {PublicKeyCredentialHints[]} [hints]: Can contain a list of \"client-device\", \"hybrid\" or \"security-key\"\n * @param {boolean} [attestation=false] If enabled, the device attestation and clientData will be provided as Base64url encoded binary data. Note that this is not available on some platforms.\n * @param {'discouraged'|'preferred'|'required'} [discoverable] A \"discoverable\" credential can be selected using `authenticate(...)` without providing credential IDs.\n * Instead, a native pop-up will appear for user selection.\n * This may have an impact on the \"passkeys\" user experience and syncing behavior of the key.\n */\nexport async function register(options: RegisterOptions): Promise {\n\n if (!options.challenge)\n throw new Error('\"challenge\" required')\n\n if (!options.user)\n throw new Error('\"user\" required')\n\n if (!utils.isBase64url(options.challenge))\n throw new Error('Provided challenge is not properly encoded in Base64url')\n\n const user: User = typeof (options.user) === 'string' ? { name: options.user } : options.user\n if (!user.id)\n user.id = crypto.randomUUID()\n\n const creationOptions: WebAuthnCreateOptions = {\n challenge: utils.parseBase64url(options.challenge),\n rp: {\n id: options.domain ?? window.location.hostname,\n name: options.domain ?? window.location.hostname\n },\n user: {\n id: utils.toBuffer(user.id),\n name: user.name,\n displayName: user.displayName ?? user.name,\n },\n hints: options.hints,\n pubKeyCredParams: [\n { alg: -7, type: \"public-key\" }, // ES256 (Webauthn's default algorithm)\n { alg: -257, type: \"public-key\" }, // RS256 (for older Windows Hello and others)\n ],\n timeout: options.timeout,\n authenticatorSelection: {\n userVerification: options.userVerification,\n authenticatorAttachment: getAuthAttachment(options.hints),\n residentKey: options.discoverable ?? 'preferred', // see https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#residentkey\n requireResidentKey: (options.discoverable === 'required') // mainly for backwards compatibility, see https://www.w3.org/TR/webauthn/#dictionary-authenticatorSelection\n },\n attestation: \"direct\"\n }\n\n console.debug(creationOptions)\n\n if (ongoingAuth != null)\n ongoingAuth.abort('Cancel ongoing authentication')\n ongoingAuth = new AbortController();\n\n const raw = await navigator.credentials.create({\n publicKey: creationOptions,\n signal: ongoingAuth?.signal\n }) as PublicKeyCredential\n const response = raw.response as AuthenticatorAttestationResponse\n\n ongoingAuth = null;\n\n console.debug(raw)\n\n if (raw.type != \"public-key\")\n throw \"Unexpected credential type!\";\n\n const publicKey = response.getPublicKey();\n if (!publicKey)\n throw \"Non-compliant browser or authenticator!\"\n\n // This should provide the same as `response.toJson()` which is sadly only available on FireFox\n const json: RegistrationJSON = {\n type: raw.type,\n id: raw.id,\n rawId: utils.toBase64url(raw.rawId), // Same as ID, but useful in tests\n authenticatorAttachment: raw.authenticatorAttachment as AuthenticatorAttachment,\n clientExtensionResults: raw.getClientExtensionResults(),\n response: {\n attestationObject: utils.toBase64url(response.attestationObject),\n authenticatorData: utils.toBase64url(response.getAuthenticatorData()),\n clientDataJSON: utils.toBase64url(response.clientDataJSON),\n publicKey: utils.toBase64url(publicKey),\n publicKeyAlgorithm: response.getPublicKeyAlgorithm(),\n transports: response.getTransports() as AuthenticatorTransport[],\n },\n user, // That's our own addition \n }\n return json\n}\n\nexport async function isAutocompleteAvailable() {\n return PublicKeyCredential.isConditionalMediationAvailable && PublicKeyCredential.isConditionalMediationAvailable();\n}\n\n/**\n * Signs a challenge using one of the provided credentials IDs in order to authenticate the user.\n *\n * @param {string[]} credentialIds The list of credential IDs that can be used for signing.\n * @param {string} challenge A server-side randomly generated string, the base64 encoded version will be signed.\n * @param {number} [timeout=60000] Number of milliseconds the user has to respond to the biometric/PIN check.\n * @param {'required'|'preferred'|'discouraged'} [userVerification='required'] Whether to prompt for biometric/PIN check or not.\n * @param {boolean} [conditional] Does not return directly, but only when the user has selected a credential in the input field with `autocomplete=\"username webauthn\"`\n */\nexport async function authenticate(options: AuthenticateOptions): Promise {\n if (!utils.isBase64url(options.challenge))\n throw new Error('Provided challenge is not properly encoded in Base64url')\n\n if (options.autocomplete && !(await isAutocompleteAvailable()))\n throw new Error('PAsskeys autocomplete with conditional mediation is not available in this browser.')\n\n let authOptions: WebAuthnGetOptions = {\n challenge: utils.parseBase64url(options.challenge),\n rpId: options.domain ?? window.location.hostname,\n allowCredentials: options.allowCredentials?.map(toPublicKeyCredentialDescriptor),\n hints: options.hints,\n userVerification: options.userVerification,\n timeout: options.timeout,\n }\n\n console.debug(authOptions)\n\n if(ongoingAuth != null)\n ongoingAuth.abort('Cancel ongoing authentication')\n \n if(options.autocomplete)\n ongoingAuth = new AbortController();\n \n const raw = await navigator.credentials.get({\n publicKey: authOptions,\n mediation: options.autocomplete ? 'conditional' : undefined,\n signal: ongoingAuth?.signal\n }) as PublicKeyCredential\n\n if (raw.type != \"public-key\")\n throw \"Unexpected credential type!\";\n\n ongoingAuth = null;\n\n console.debug(raw)\n\n const response = raw.response as AuthenticatorAssertionResponse\n\n // This should provide the same as `response.toJson()` which is sadly only available on FireFox\n const json: AuthenticationJSON = {\n clientExtensionResults: raw.getClientExtensionResults(),\n id: raw.id,\n rawId: utils.toBase64url(raw.rawId),\n type: raw.type,\n authenticatorAttachment: raw.authenticatorAttachment as AuthenticatorAttachment,\n response: {\n authenticatorData: utils.toBase64url(response.authenticatorData),\n clientDataJSON: utils.toBase64url(response.clientDataJSON),\n signature: utils.toBase64url(response.signature),\n userHandle: response.userHandle ? utils.toBase64url(response.userHandle) : undefined\n }\n }\n\n return json\n}\n\nfunction toPublicKeyCredentialDescriptor(cred: Base64URLString | CredentialDescriptor): PublicKeyCredentialDescriptor {\n if(typeof cred === 'string') {\n return {\n id: utils.parseBase64url(cred),\n type: 'public-key'\n }\n }\n else {\n return {\n id: utils.parseBase64url(cred.id),\n type: 'public-key',\n transports: cred.transports as AuthenticatorTransport[]\n }\n }\n}\n", "/********************************\n Encoding/Decoding Utils\n********************************/\n\nimport { Base64URLString } from \"./types\"\n\n\nexport function toBuffer(txt :string) :ArrayBuffer {\n return Uint8Array.from(txt, c => c.charCodeAt(0)).buffer\n}\n\nexport function parseBuffer(buffer :ArrayBuffer) :string {\n return String.fromCharCode(...new Uint8Array(buffer))\n}\n\n\nexport function isBase64url(txt :string) :boolean {\n return txt.match(/^[a-zA-Z0-9\\-_]+=*$/) !== null\n}\n\nexport function toBase64url(buffer :ArrayBuffer) :Base64URLString {\n const txt = btoa(parseBuffer(buffer)) // base64\n return txt.replaceAll('+', '-').replaceAll('/', '_')\n}\n\nexport function parseBase64url(txt :Base64URLString) :ArrayBuffer {\n txt = txt.replaceAll('-', '+').replaceAll('_', '/') // base64url -> base64\n return toBuffer(atob(txt))\n}\n\n\nexport async function sha256(buffer :ArrayBuffer) :Promise {\n return await crypto.subtle.digest('SHA-256', buffer)\n}\n\nexport function bufferToHex (buffer :ArrayBuffer) :string {\n return [...new Uint8Array (buffer)]\n .map (b => b.toString (16).padStart (2, \"0\"))\n .join (\"\");\n}\n\n\nexport function concatenateBuffers(buffer1 :ArrayBuffer, buffer2 :ArrayBuffer) {\n var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);\n tmp.set(new Uint8Array(buffer1), 0);\n tmp.set(new Uint8Array(buffer2), buffer1.byteLength);\n return tmp;\n };", "import { authenticatorMetadata, parsers } from \"./index\";\nimport { parseAuthenticator, parseClient, toAuthenticationInfo } from \"./parsers\";\nimport { AuthenticationJSON, NamedAlgo, RegistrationJSON, RegistrationInfo, AuthenticationInfo, Base64URLString, CollectedClientData, UserInfo, CredentialInfo, AuthenticatorInfo, AuthenticatorParsed } from \"./types\";\nimport * as utils from './utils'\n\n\nexport function randomChallenge() {\n const buffer = crypto.getRandomValues(new Uint8Array(18)); // > 128 bits, a multiple of 3 bytes to have base64 encoding without padding\n return utils.toBase64url(buffer);\n}\n\n\n\nasync function isValid(validator :any, value :any) :Promise {\n if(typeof validator === 'function') {\n const res = validator(value)\n if(res instanceof Promise)\n return await res\n else\n return res\n }\n // the validator can be a single value too\n return validator === value\n}\n\nasync function isNotValid(validator :any, value :any) :Promise {\n return !(await isValid(validator, value))\n}\n\ninterface RegistrationChecks {\n challenge: string | Function,\n origin: string | Function\n}\n\n\n\nexport async function verifyRegistration(registrationJson: RegistrationJSON, expected: RegistrationChecks): Promise {\n const client = parseClient(registrationJson.response.clientDataJSON)\n const authenticator = parseAuthenticator(registrationJson.response.authenticatorData);\n const aaguid = authenticator.aaguid;\n\n if(!aaguid) // should never happen, worst case should be a fallback to \"zeroed\" aaguid\n throw new Error(\"Unexpected errror, no AAGUID.\")\n\n if (client.type !== \"webauthn.create\")\n throw new Error(`Unexpected ClientData type: ${client.type}`)\n\n if (await isNotValid(expected.origin, client.origin))\n throw new Error(`Unexpected ClientData origin: ${client.origin}`)\n\n if (await isNotValid(expected.challenge, client.challenge))\n throw new Error(`Unexpected ClientData challenge: ${client.challenge}`)\n\n return parsers.toRegistrationInfo(registrationJson, authenticator)\n}\n\n\n\ninterface AuthenticationChecks {\n challenge: string | Function,\n origin: string | Function,\n userVerified: boolean,\n counter?: number, // Made optional according to https://github.com/passwordless-id/webauthn/issues/38\n domain ?:string, // Same as `rp.id`\n verbose?: boolean\n}\n\n\n\nexport async function verifyAuthentication(authenticationJson: AuthenticationJSON, credential: CredentialInfo, expected: AuthenticationChecks): Promise {\n if (authenticationJson.id !== credential.id)\n throw new Error(`Credential ID mismatch: ${authenticationJson.id} vs ${credential.id}`)\n\n const isValidSignature: boolean = await verifySignature({\n algorithm: credential.algorithm,\n publicKey: credential.publicKey,\n authenticatorData: authenticationJson.response.authenticatorData,\n clientData: authenticationJson.response.clientDataJSON,\n signature: authenticationJson.response.signature,\n verbose: expected.verbose\n })\n\n if(!isValidSignature)\n throw new Error(`Invalid signature: ${authenticationJson.response.signature}`)\n\n const client :CollectedClientData = parseClient(authenticationJson.response.clientDataJSON);\n const authenticator :AuthenticatorParsed = parseAuthenticator(authenticationJson.response.authenticatorData);\n\n if(expected.verbose) {\n console.debug(client)\n console.debug(authenticator)\n }\n \n if (client.type !== \"webauthn.get\")\n throw new Error(`Unexpected clientData type: ${client.type}`)\n\n if (await isNotValid(expected.origin, client.origin))\n throw new Error(`Unexpected ClientData origin: ${client.origin}`)\n\n if (await isNotValid(expected.challenge, client.challenge))\n throw new Error(`Unexpected ClientData challenge: ${client.challenge}`)\n\n // this only works because we consider `rp.origin` and `rp.id` to be the same during authentication/registration\n const rpId = expected.domain ?? new URL(client.origin).hostname\n const expectedRpIdHash = utils.toBase64url(await utils.sha256(utils.toBuffer(rpId)))\n if (authenticator.rpIdHash !== expectedRpIdHash)\n throw new Error(`Unexpected RpIdHash: ${authenticator.rpIdHash} vs ${expectedRpIdHash}`)\n\n if (!authenticator.flags.userPresent)\n throw new Error(`Unexpected authenticator flags: missing userPresent`)\n\n if (!authenticator.flags.userVerified && expected.userVerified)\n throw new Error(`Unexpected authenticator flags: missing userVerified`)\n\n if (expected.counter && authenticator.signCount <= expected.counter)\n throw new Error(`Unexpected authenticator counter: ${authenticator.signCount} (should be > ${expected.counter})`)\n\n return toAuthenticationInfo(authenticationJson, authenticator)\n}\n\n\n// https://w3c.github.io/webauthn/#sctn-public-key-easy\n// https://www.iana.org/assignments/cose/cose.xhtml#algorithms\n/*\nUser agents MUST be able to return a non-null value for getPublicKey() when the credential public key has a COSEAlgorithmIdentifier value of:\n\n-7 (ES256), where kty is 2 (with uncompressed points) and crv is 1 (P-256).\n\n-257 (RS256).\n\n-8 (EdDSA), where crv is 6 (Ed25519).\n*/\nfunction getAlgoParams(algorithm: NamedAlgo): AlgoParams {\n switch (algorithm) {\n case 'RS256':\n return {\n name: 'RSASSA-PKCS1-v1_5',\n hash: 'SHA-256'\n };\n case 'ES256':\n return {\n name: 'ECDSA',\n namedCurve: 'P-256',\n hash: 'SHA-256',\n };\n // case 'EdDSA': Not supported by browsers\n default:\n throw new Error(`Unknown or unsupported crypto algorithm: ${algorithm}. Only 'RS256' and 'ES256' are supported.`)\n }\n}\n\ntype AlgoParams = RsaPssParams | EcKeyImportParams | EcdsaParams\n\nexport async function parseCryptoKey(algorithm: NamedAlgo, publicKey: string): Promise {\n const algoParams = getAlgoParams(algorithm)\n const buffer = utils.parseBase64url(publicKey)\n return crypto.subtle.importKey('spki', buffer, algoParams, false, ['verify'])\n}\n\n\n\ntype VerifyParams = {\n algorithm: NamedAlgo,\n publicKey: Base64URLString,\n authenticatorData: Base64URLString,\n clientData: Base64URLString,\n signature: Base64URLString,\n verbose?: boolean, // Enables debug logs containing sensitive data like crypto keys\n}\n\n\n// https://w3c.github.io/webauthn/#sctn-verifying-assertion\n// https://w3c.github.io/webauthn/#sctn-signature-attestation-types\n/* Emphasis mine:\n\n6.5.6. Signature Formats for Packed Attestation, FIDO U2F Attestation, and **Assertion Signatures**\n\n[...] For COSEAlgorithmIdentifier -7 (ES256) [...] the sig value MUST be encoded as an ASN.1 [...]\n[...] For COSEAlgorithmIdentifier -257 (RS256) [...] The signature is not ASN.1 wrapped.\n[...] For COSEAlgorithmIdentifier -37 (PS256) [...] The signature is not ASN.1 wrapped.\n*/\n// see also https://gist.github.com/philholden/50120652bfe0498958fd5926694ba354\nexport async function verifySignature({ algorithm, publicKey, authenticatorData, clientData, signature, verbose }: VerifyParams): Promise {\n let cryptoKey = await parseCryptoKey(algorithm, publicKey)\n\n if(verbose) {\n console.debug(cryptoKey)\n }\n\n let clientHash = await utils.sha256(utils.parseBase64url(clientData));\n\n // during \"login\", the authenticatorData is exactly 37 bytes\n let comboBuffer = utils.concatenateBuffers(utils.parseBase64url(authenticatorData), clientHash)\n\n if(verbose) {\n console.debug('Algorithm: ' + algorithm)\n console.debug('Public key: ' + publicKey)\n console.debug('Data: ' + utils.toBase64url(comboBuffer))\n console.debug('Signature: ' + signature)\n }\n\n // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify\n let signatureBuffer = utils.parseBase64url(signature)\n if(algorithm == 'ES256')\n signatureBuffer = convertASN1toRaw(signatureBuffer)\n\n const algoParams = getAlgoParams(algorithm)\n const isValid = await crypto.subtle.verify(algoParams, cryptoKey, signatureBuffer, comboBuffer)\n\n return isValid\n}\n\nfunction convertASN1toRaw(signatureBuffer :ArrayBuffer) {\n // Convert signature from ASN.1 sequence to \"raw\" format\n const signature = new Uint8Array(signatureBuffer);\n const rStart = signature[4] === 0 ? 5 : 4;\n const rEnd = rStart + 32;\n const sStart = signature[rEnd + 2] === 0 ? rEnd + 3 : rEnd + 2;\n const r = signature.slice(rStart, rEnd);\n const s = signature.slice(sStart);\n return new Uint8Array([...r, ...s]);\n}", "import * as utils from './utils'\nimport { Base64URLString, CollectedClientData, NamedAlgo, AuthenticatorParsed, RegistrationJSON, RegistrationInfo, UserInfo, AuthenticationInfo, AuthenticationJSON } from './types'\nimport { authenticatorMetadata } from './authenticatorMetadata'\n\nconst utf8Decoder = new TextDecoder('utf-8')\n\n\ninterface ClientInfo {\n type: \"webauthn.create\" | \"webauthn.get\"\n challenge: string\n origin: string\n crossOrigin: boolean\n tokenBindingId?: {\n id: string\n status: string\n }\n extensions?: any\n}\n\n \nexport function parseClient(data :Base64URLString|ArrayBuffer) :CollectedClientData {\n if(typeof data == 'string')\n data = utils.parseBase64url(data)\n return JSON.parse(utf8Decoder.decode(data))\n}\n\n\nexport function parseAuthenticator(authData :Base64URLString|ArrayBuffer) :AuthenticatorParsed {\n if(typeof authData == 'string')\n authData = utils.parseBase64url(authData)\n \n //console.debug(authData)\n let flags = new DataView(authData.slice(32,33)).getUint8(0)\n //console.debug(flags)\n\n // https://w3c.github.io/webauthn/#sctn-authenticator-data\n return {\n rpIdHash: extractRpIdHash(authData),\n flags: {\n userPresent: !!(flags & 1),\n //reserved1: !!(flags & 2),\n userVerified: !!(flags & 4),\n backupEligibility: !!(flags & 8),\n backupState: !!(flags & 16),\n //reserved2: !!(flags & 32),\n attestedData: !!(flags & 64),\n extensionsIncluded: !!(flags & 128)\n },\n signCount: new DataView(authData.slice(33,37)).getUint32(0, false), // Big-Endian!\n aaguid: extractAaguid(authData),\n //credentialId: extractCredentialId() \n }\n}\n\nfunction extractRpIdHash(authData :ArrayBuffer) :Base64URLString {\n return utils.toBase64url(authData.slice(0,32))\n}\n\n/**\n * Returns the AAGUID in the format \"00000000-0000-0000-0000-000000000000\"\n */\nfunction extractAaguid(authData :ArrayBuffer) :string {\n if(authData.byteLength < 53)\n return \"00000000-0000-0000-0000-000000000000\"\n const buffer = authData.slice(37, 53) // 16 byte\n const hex = utils.bufferToHex(buffer)\n const aaguid :string = `${hex.substring(0,8)}-${hex.substring(8,12)}-${hex.substring(12,16)}-${hex.substring(16,20)}-${hex.substring(20,32)}`\n return aaguid // example: \"d41f5a69-b817-4144-a13c-9ebd6d9254d6\"\n}\n\n\n\nexport function getAlgoName(num :COSEAlgorithmIdentifier) :NamedAlgo {\n switch(num) {\n case -7: return \"ES256\"\n case -8: return \"EdDSA\"\n case -257: return \"RS256\"\n default: throw new Error(`Unknown algorithm code: ${num}`)\n }\n}\n\n\nexport function parseRegistration(registrationJson :RegistrationJSON) :RegistrationInfo {\n const authenticator = parseAuthenticator(registrationJson.response.authenticatorData);\n return toRegistrationInfo(registrationJson, authenticator);\n}\n\nexport function toRegistrationInfo(registrationJson :RegistrationJSON, authenticator :AuthenticatorParsed) :RegistrationInfo {\n const aaguid = authenticator.aaguid\n return {\n authenticator: {\n aaguid,\n counter: authenticator.signCount,\n icon_light: 'https://webauthn.passwordless.id/authenticators/' + aaguid + '-light.png',\n icon_dark: 'https://webauthn.passwordless.id/authenticators/' + aaguid + '-dark.png',\n name: authenticatorMetadata[aaguid] ?? 'Unknown',\n },\n credential: {\n id: registrationJson.id,\n publicKey: registrationJson.response.publicKey,\n algorithm: getAlgoName(registrationJson.response.publicKeyAlgorithm),\n transports: registrationJson.response.transports\n },\n synced: authenticator.flags.backupEligibility,\n user: registrationJson.user as UserInfo, // That's specific to this library\n userVerified: authenticator.flags.userVerified,\n }\n}\n\nexport function toAuthenticationInfo(authenticationJson :AuthenticationJSON, authenticator :AuthenticatorParsed) :AuthenticationInfo {\n return {\n credentialId: authenticationJson.id,\n userId: authenticationJson.response.userHandle,\n counter: authenticator.signCount,\n userVerified: authenticator.flags.userVerified,\n authenticatorAttachment: authenticationJson.authenticatorAttachment\n }\n}\n\n\nexport function parseAuthentication(authenticationJson :AuthenticationJSON) :AuthenticationInfo {\n const authenticator = parseAuthenticator(authenticationJson.response.authenticatorData);\n return toAuthenticationInfo(authenticationJson, authenticator);\n}\n", "/**\n * The source comes from\n * \"official\" https://mds.fidoalliance.org/\n * and the\n * \"community-driven\" https://github.com/passkeydeveloper/passkey-authenticator-aaguids\n * combined together.\n */\nexport const authenticatorMetadata :Record = {\n\t\"00000000-0000-0000-0000-000000000000\": \"Unknown authenticator\",\n\t\"0076631b-d4a0-427f-5773-0ec71c9e0279\": \"HYPR FIDO2 Authenticator\",\n\t\"07a9f89c-6407-4594-9d56-621d5f1e358b\": \"NXP Semiconductros FIDO2 Conformance Testing CTAP2 Authenticator\",\n\t\"08987058-cadc-4b81-b6e1-30de50dcbe96\": \"Windows Hello\",\n\t\"092277e5-8437-46b5-b911-ea64b294acb7\": \"Taglio CTAP2.1 CS\",\n\t\"09591fc6-9811-48f7-8f57-b9f23df6413f\": \"Pone Biometrics OFFPAD Authenticator\",\n\t\"0acf3011-bc60-f375-fb53-6f05f43154e0\": \"Nymi FIDO2 Authenticator\",\n\t\"0bb43545-fd2c-4185-87dd-feb0b2916ace\": \"Security Key NFC by Yubico - Enterprise Edition\",\n\t\"0d9b2e56-566b-c393-2940-f821b7f15d6d\": \"Excelsecu eSecu FIDO2 Pro Security Key\",\n\t\"0ea242b4-43c4-4a1b-8b17-dd6d0b6baec6\": \"Keeper\",\n\t\"1105e4ed-af1d-02ff-ffff-ffffffffffff\": \"Egomet FIDO2 Authenticator for Android\",\n\t\"12ded745-4bed-47d4-abaa-e713f51d6393\": \"Feitian AllinOne FIDO2 Authenticator\",\n\t\"149a2021-8ef6-4133-96b8-81f8d5b7f1f5\": \"Security Key by Yubico with NFC\",\n\t\"17290f1e-c212-34d0-1423-365d729f09d9\": \"Thales PIN iOS SDK\",\n\t\"175cd298-83d2-4a26-b637-313c07a6434e\": \"Chunghwa Telecom FIDO2 Smart Card Authenticator\",\n\t\"19083c3d-8383-4b18-bc03-8f1c9ab2fd1b\": \"YubiKey 5 Series\",\n\t\"1c086528-58d5-f211-823c-356786e36140\": \"Atos CardOS FIDO2\",\n\t\"20f0be98-9af9-986a-4b42-8eca4acb28e4\": \"Excelsecu eSecu FIDO2 Fingerprint Security Key\",\n\t\"2194b428-9397-4046-8f39-007a1605a482\": \"IDPrime 931 Fido\",\n\t\"234cd403-35a2-4cc2-8015-77ea280c77f5\": \"Feitian ePass FIDO2-NFC Series (CTAP2.1, CTAP2.0, U2F)\",\n\t\"23786452-f02d-4344-87ed-aaf703726881\": \"SafeNet eToken Fusion CC\",\n\t\"2772ce93-eb4b-4090-8b73-330f48477d73\": \"Security Key NFC by Yubico - Enterprise Edition Preview\",\n\t\"2c0df832-92de-4be1-8412-88a8f074df4a\": \"Feitian FIDO Smart Card\",\n\t\"2d3bec26-15ee-4f5d-88b2-53622490270b\": \"HID Crescendo Key V2\",\n\t\"2fc0579f-8113-47ea-b116-bb5a8db9202a\": \"YubiKey 5 Series with NFC\",\n\t\"2ffd6452-01da-471f-821b-ea4bf6c8676a\": \"IDPrime 941 Fido\",\n\t\"30b5035e-d297-4fc1-b00b-addc96ba6a97\": \"OneSpan FIDO Touch\",\n\t\"30b5035e-d297-4ff1-b00b-addc96ba6a98\": \"OneSpan DIGIPASS FX1 BIO\",\n\t\"3124e301-f14e-4e38-876d-fbeeb090e7bf\": \"YubiKey 5 Series with Lightning Preview\",\n\t\"31c3f7ff-bf15-4327-83ec-9336abcbcd34\": \"WinMagic FIDO Eazy - Software\",\n\t\"341e4da9-3c2e-8103-5a9f-aad887135200\": \"Ledger Nano S FIDO2 Authenticator\",\n\t\"34f5766d-1536-4a24-9033-0e294e510fb0\": \"YubiKey 5 Series with NFC Preview\",\n\t\"361a3082-0278-4583-a16f-72a527f973e4\": \"eWBM eFA500 FIDO2 Authenticator\",\n\t\"3789da91-f943-46bc-95c3-50ea2012f03a\": \"NEOWAVE Winkeo FIDO2\",\n\t\"39a5647e-1853-446c-a1f6-a79bae9f5bc7\": \"IDmelon\",\n\t\"3b1adb99-0dfe-46fd-90b8-7f7614a4de2a\": \"GoTrust Idem Key FIDO2 Authenticator\",\n\t\"3e078ffd-4c54-4586-8baa-a77da113aec5\": \"Hideez Key 3 FIDO2\",\n\t\"3e22415d-7fdf-4ea4-8a0c-dd60c4249b9d\": \"Feitian iePass FIDO Authenticator\",\n\t\"3f59672f-20aa-4afe-b6f4-7e5e916b6d98\": \"Arculus FIDO 2.1 Key Card [P71]\",\n\t\"42b4fb4a-2866-43b2-9bf7-6c6669c2e5d3\": \"Google Titan Security Key v2\",\n\t\"454e5346-4944-4ffd-6c93-8e9267193e9a\": \"Ensurity ThinC\",\n\t\"454e5346-4944-4ffd-6c93-8e9267193e9b\": \"Ensurity AUTH BioPro\",\n\t\"47ab2fb4-66ac-4184-9ae1-86be814012d5\": \"Security Key NFC by Yubico - Enterprise Edition\",\n\t\"4b3f8944-d4f2-4d21-bb19-764a986ec160\": \"KeyXentic FIDO2 Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"4c0cf95d-2f40-43b5-ba42-4c83a11c04ba\": \"Feitian BioPass FIDO2 Pro Authenticator\",\n\t\"4c50ff10-1057-4fc6-b8ed-43a529530c3c\": \"ImproveID Authenticator\",\n\t\"4d41190c-7beb-4a84-8018-adf265a6352d\": \"Thales IDPrime FIDO Bio\",\n\t\"4e768f2c-5fab-48b3-b300-220eb487752b\": \"Hideez Key 4 FIDO2 SDK\",\n\t\"504d7149-4e4c-3841-4555-55445a677357\": \"WiSECURE AuthTron USB FIDO2 Authenticator\",\n\t\"50726f74-6f6e-5061-7373-50726f746f6e\": \"Proton Pass\",\n\t\"50a45b0c-80e7-f944-bf29-f552bfa2e048\": \"ACS FIDO Authenticator\",\n\t\"516d3969-5a57-5651-5958-4e7a49434167\": \"SmartDisplayer BobeePass FIDO2 Authenticator\",\n\t\"531126d6-e717-415c-9320-3d9aa6981239\": \"Dashlane\",\n\t\"53414d53-554e-4700-0000-000000000000\": \"Samsung Pass\",\n\t\"5343502d-5343-5343-6172-644649444f32\": \"ESS Smart Card Inc. Authenticator\",\n\t\"54d9fee8-e621-4291-8b18-7157b99c5bec\": \"HID Crescendo Enabled\",\n\t\"5626bed4-e756-430b-a7ff-ca78c8b12738\": \"VALMIDO PRO FIDO\",\n\t\"58b44d0b-0a7c-f33a-fd48-f7153c871352\": \"Ledger Nano S Plus FIDO2 Authenticator\",\n\t\"5b0e46ba-db02-44ac-b979-ca9b84f5e335\": \"YubiKey 5 FIPS Series with Lightning Preview\",\n\t\"5ca1ab1e-1337-fa57-f1d0-a117e71ca702\": \"Allthenticator App: roaming BLE FIDO2 Allthenticator for Windows, Mac, Linux, and Allthenticate door readers\",\n\t\"5d629218-d3a5-11ed-afa1-0242ac120002\": \"Swissbit iShield Key Pro\",\n\t\"5fdb81b8-53f0-4967-a881-f5ec26fe4d18\": \"VinCSS FIDO2 Authenticator\",\n\t\"6002f033-3c07-ce3e-d0f7-0ffe5ed42543\": \"Excelsecu eSecu FIDO2 Fingerprint Key\",\n\t\"6028b017-b1d4-4c02-b4b3-afcdafc96bb2\": \"Windows Hello\",\n\t\"61250591-b2bc-4456-b719-0b17be90bb30\": \"eWBM eFPA FIDO2 Authenticator\",\n\t\"62e54e98-c209-4df3-b692-de71bb6a8528\": \"YubiKey 5 FIPS Series with NFC Preview\",\n\t\"664d9f67-84a2-412a-9ff7-b4f7d8ee6d05\": \"OpenSK authenticator\",\n\t\"66a0ccb3-bd6a-191f-ee06-e375c50b9846\": \"Thales Bio iOS SDK\",\n\t\"692db549-7ae5-44d5-a1e5-dd20a493b723\": \"HID Crescendo Key\",\n\t\"69700f79-d1fb-472e-bd9b-a3a3b9a9eda0\": \"Pone Biometrics OFFPAD Authenticator\",\n\t\"6d44ba9b-f6ec-2e49-b930-0c8fe920cb73\": \"Security Key by Yubico with NFC\",\n\t\"6dae43be-af9c-417b-8b9f-1b611168ec60\": \"Dapple Authenticator from Dapple Security Inc.\",\n\t\"73402251-f2a8-4f03-873e-3cb6db604b03\": \"uTrust FIDO2 Security Key\",\n\t\"73bb0cd4-e502-49b8-9c6f-b59445bf720b\": \"YubiKey 5 FIPS Series\",\n\t\"74820b05-a6c9-40f9-8fb0-9f86aca93998\": \"SafeNet eToken Fusion\",\n\t\"760eda36-00aa-4d29-855b-4012a182cdeb\": \"Security Key NFC by Yubico Preview\",\n\t\"77010bd7-212a-4fc9-b236-d2ca5e9d4084\": \"Feitian BioPass FIDO2 Authenticator\",\n\t\"771b48fd-d3d4-4f74-9232-fc157ab0507a\": \"Edge on Mac\",\n\t\"7d1351a6-e097-4852-b8bf-c9ac5c9ce4a3\": \"YubiKey Bio Series - Multi-protocol Edition\",\n\t\"7d2afadd-bf6b-44a2-a66b-e831fceb8eff\": \"Taglio CTAP2.1 EP\",\n\t\"7e3f3d30-3557-4442-bdae-139312178b39\": \"RSA DS100\",\n\t\"820d89ed-d65a-409e-85cb-f73f0578f82a\": \"IDmelon iOS Authenticator\",\n\t\"833b721a-ff5f-4d00-bb2e-bdda3ec01e29\": \"Feitian ePass FIDO2 Authenticator\",\n\t\"83c47309-aabb-4108-8470-8be838b573cb\": \"YubiKey Bio Series (Enterprise Profile)\",\n\t\"85203421-48f9-4355-9bc8-8a53846e5083\": \"YubiKey 5 FIPS Series with Lightning\",\n\t\"87dbc5a1-4c94-4dc8-8a47-97d800fd1f3c\": \"eWBM eFA320 FIDO2 Authenticator\",\n\t\"8836336a-f590-0921-301d-46427531eee6\": \"Thales Bio Android SDK\",\n\t\"8876631b-d4a0-427f-5773-0ec71c9e0279\": \"Solo Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"88bbd2f0-342a-42e7-9729-dd158be5407a\": \"Precision InnaIT Key FIDO 2 Level 2 certified\",\n\t\"891494da-2c90-4d31-a9cd-4eab0aed1309\": \"S\u00E9same\",\n\t\"8976631b-d4a0-427f-5773-0ec71c9e0279\": \"Solo Tap Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"89b19028-256b-4025-8872-255358d950e4\": \"Sentry Enterprises CTAP2 Authenticator\",\n\t\"8c97a730-3f7b-41a6-87d6-1e9b62bda6f0\": \"FT-JCOS FIDO Fingerprint Card\",\n\t\"8d1b1fcb-3c76-49a9-9129-5515b346aa02\": \"IDEMIA ID-ONE Card\",\n\t\"91ad6b93-264b-4987-8737-3a690cad6917\": \"Token Ring FIDO2 Authenticator\",\n\t\"931327dd-c89b-406c-a81e-ed7058ef36c6\": \"Swissbit iShield Key FIDO2\",\n\t\"95442b2e-f15e-4def-b270-efb106facb4e\": \"eWBM eFA310 FIDO2 Authenticator\",\n\t\"95e4d58c-056e-4a65-866d-f5a69659e880\": \"TruU Windows Authenticator\",\n\t\"970c8d9c-19d2-46af-aa32-3f448db49e35\": \"WinMagic FIDO Eazy - TPM\",\n\t\"973446ca-e21c-9a9b-99f5-9b985a67af0f\": \"ACS FIDO Authenticator Card\",\n\t\"9876631b-d4a0-427f-5773-0ec71c9e0279\": \"Somu Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"998f358b-2dd2-4cbe-a43a-e8107438dfb3\": \"OnlyKey Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"99bf4610-ec26-4252-b31f-7380ccd59db5\": \"ZTPass Card\",\n\t\"9c835346-796b-4c27-8898-d6032f515cc5\": \"Cryptnox FIDO2\",\n\t\"9d3df6ba-282f-11ed-a261-0242ac120002\": \"Arculus FIDO2/U2F Key Card\",\n\t\"9ddd1817-af5a-4672-a2b9-3e3dd95000a9\": \"Windows Hello\",\n\t\"9f0d8150-baa5-4c00-9299-ad62c8bb4e87\": \"GoTrust Idem Card FIDO2 Authenticator\",\n\t\"9f77e279-a6e2-4d58-b700-31e5943c6a98\": \"Hyper FIDO Pro\",\n\t\"a02167b9-ae71-4ac7-9a07-06432ebb6f1c\": \"YubiKey 5 Series with Lightning\",\n\t\"a1f52be5-dfab-4364-b51c-2bd496b14a56\": \"OCTATCO EzFinger2 FIDO2 AUTHENTICATOR\",\n\t\"a25342c0-3cdc-4414-8e46-f4807fca511c\": \"YubiKey 5 Series with NFC\",\n\t\"a3975549-b191-fd67-b8fb-017e2917fdb3\": \"Excelsecu eSecu FIDO2 NFC Security Key\",\n\t\"a4e9fc6d-4cbe-4758-b8ba-37598bb5bbaa\": \"Security Key NFC by Yubico\",\n\t\"ab32f0c6-2239-afbb-c470-d2ef4e254db6\": \"TEST (DUMMY RECORD)\",\n\t\"ab32f0c6-2239-afbb-c470-d2ef4e254db7\": \"TOKEN2 FIDO2 Security Key\",\n\t\"adce0002-35bc-c60a-648b-0b25f1f05503\": \"Chrome on Mac\",\n\t\"aeb6569c-f8fb-4950-ac60-24ca2bbe2e52\": \"HID Crescendo C2300\",\n\t\"b267239b-954f-4041-a01b-ee4f33c145b6\": \"authenton1 - CTAP2.1\",\n\t\"b50d5e0a-7f81-4959-9b12-f45407407503\": \"IDPrime 3940 FIDO\",\n\t\"b5397666-4885-aa6b-cebf-e52262a439a2\": \"Chromium Browser\",\n\t\"b6ede29c-3772-412c-8a78-539c1f4c62d2\": \"Feitian BioPass FIDO2 Plus Authenticator\",\n\t\"b84e4048-15dc-4dd0-8640-f4f60813c8af\": \"NordPass\",\n\t\"b92c3f9a-c014-4056-887f-140a2501163b\": \"Security Key by Yubico\",\n\t\"b93fd961-f2e6-462f-b122-82002247de78\": \"Android Authenticator with SafetyNet Attestation\",\n\t\"ba76a271-6eb6-4171-874d-b6428dbe3437\": \"ATKey.ProS\",\n\t\"ba86dc56-635f-4141-aef6-00227b1b9af6\": \"TruU Windows Authenticator\",\n\t\"bada5566-a7aa-401f-bd96-45619a55120d\": \"1Password\",\n\t\"bbf4b6a7-679d-f6fc-c4f2-8ac0ddf9015a\": \"Excelsecu eSecu FIDO2 PRO Security Key\",\n\t\"bc2fe499-0d8e-4ffe-96f3-94a82840cf8c\": \"OCTATCO EzQuant FIDO2 AUTHENTICATOR\",\n\t\"be727034-574a-f799-5c76-0929e0430973\": \"Crayonic KeyVault K1 (USB-NFC-BLE FIDO2 Authenticator)\",\n\t\"c1f9a0bc-1dd2-404a-b27f-8e29047a43fd\": \"YubiKey 5 FIPS Series with NFC\",\n\t\"c5703116-972b-4851-a3e7-ae1259843399\": \"NEOWAVE Badgeo FIDO2\",\n\t\"c5ef55ff-ad9a-4b9f-b580-adebafe026d0\": \"YubiKey 5 Series with Lightning\",\n\t\"c80dbd9a-533f-4a17-b941-1a2f1c7cedff\": \"HID Crescendo C3000\",\n\t\"ca4cff1b-5a81-4404-8194-59aabcf1660b\": \"IDPrime 3930 FIDO\",\n\t\"ca87cb70-4c1b-4579-a8e8-4efdd7c007e0\": \"FIDO Alliance TruU Sample FIDO2 Authenticator\",\n\t\"cb69481e-8ff7-4039-93ec-0a2729a154a8\": \"YubiKey 5 Series\",\n\t\"cc45f64e-52a2-451b-831a-4edd8022a202\": \"ToothPic Passkey Provider\",\n\t\"cd69adb5-3c7a-deb9-3177-6800ea6cb72a\": \"Thales PIN Android SDK\",\n\t\"cdbdaea2-c415-5073-50f7-c04e968640b6\": \"Excelsecu eSecu FIDO2 Security Key\",\n\t\"cfcb13a2-244f-4b36-9077-82b79d6a7de7\": \"USB/NFC Passcode Authenticator\",\n\t\"d384db22-4d50-ebde-2eac-5765cf1e2a44\": \"Excelsecu eSecu FIDO2 Fingerprint Security Key\",\n\t\"d41f5a69-b817-4144-a13c-9ebd6d9254d6\": \"ATKey.Card CTAP2.0\",\n\t\"d548826e-79b4-db40-a3d8-11116f7e8349\": \"Bitwarden\",\n\t\"d61d3b87-3e7c-4aea-9c50-441c371903ad\": \"KeyVault Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"d7a423ad-3e19-4492-9200-78137dccc136\": \"VivoKey Apex FIDO2\",\n\t\"d821a7d4-e97c-4cb6-bd82-4237731fd4be\": \"Hyper FIDO Bio Security Key\",\n\t\"d8522d9f-575b-4866-88a9-ba99fa02f35b\": \"YubiKey Bio Series\",\n\t\"d91c5288-0ef0-49b7-b8ae-21ca0aa6b3f3\": \"KEY-ID FIDO2 Authenticator\",\n\t\"d94a29d9-52dd-4247-9c2d-8b818b610389\": \"VeriMark Guard Fingerprint Key\",\n\t\"da1fa263-8b25-42b6-a820-c0036f21ba7f\": \"ATKey.Card NFC\",\n\t\"dd4ec289-e01d-41c9-bb89-70fa845d4bf2\": \"iCloud Keychain (Managed)\",\n\t\"e1a96183-5016-4f24-b55b-e3ae23614cc6\": \"ATKey.Pro CTAP2.0\",\n\t\"e416201b-afeb-41ca-a03d-2281c28322aa\": \"ATKey.Pro CTAP2.1\",\n\t\"e77e3c64-05e3-428b-8824-0cbeb04b829d\": \"Security Key NFC by Yubico\",\n\t\"e86addcd-7711-47e5-b42a-c18257b0bf61\": \"IDCore 3121 Fido\",\n\t\"ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4\": \"Google Password Manager\",\n\t\"eabb46cc-e241-80bf-ae9e-96fa6d2975cf\": \"TOKEN2 PIN Plus Security Key Series \",\n\t\"eb3b131e-59dc-536a-d176-cb7306da10f5\": \"ellipticSecure MIRkey USB Authenticator\",\n\t\"ec31b4cc-2acc-4b8e-9c01-bade00ccbe26\": \"KeyXentic FIDO2 Secp256R1 FIDO2 CTAP2 Authenticator\",\n\t\"ee041bce-25e5-4cdb-8f86-897fd6418464\": \"Feitian ePass FIDO2-NFC Authenticator\",\n\t\"ee882879-721c-4913-9775-3dfcce97072a\": \"YubiKey 5 Series\",\n\t\"efb96b10-a9ee-4b6c-a4a9-d32125ccd4a4\": \"Safenet eToken FIDO\",\n\t\"f3809540-7f14-49c1-a8b3-8f813b225541\": \"Enpass\",\n\t\"f4c63eff-d26c-4248-801c-3736c7eaa93a\": \"FIDO KeyPass S3\",\n\t\"f56f58b3-d711-4afc-ba7d-6ac05f88cb19\": \"WinMagic FIDO Eazy - Phone\",\n\t\"f7c558a0-f465-11e8-b568-0800200c9a66\": \"KONAI Secp256R1 FIDO2 Conformance Testing CTAP2 Authenticator\",\n\t\"f8a011f3-8c0a-4d15-8006-17111f9edc7d\": \"Security Key by Yubico\",\n\t\"fa2b99dc-9e39-4257-8f92-4a30d23c4118\": \"YubiKey 5 Series with NFC\",\n\t\"fbefdf68-fe86-0106-213e-4d5fa24cbe2e\": \"Excelsecu eSecu FIDO2 NFC Security Key\",\n\t\"fbfc3007-154e-4ecc-8c0b-6e020557d7bd\": \"iCloud Keychain\",\n\t\"fcb1bcb4-f370-078c-6993-bc24d0ae3fbe\": \"Ledger Nano X FIDO2 Authenticator\",\n\t\"fdb141b2-5d84-443e-8a35-4698c205a502\": \"KeePassXC\",\n\t\"fec067a1-f1d0-4c5e-b4c0-cc3237475461\": \"KX701 SmartToken FIDO\",\n}", "import * as client from './client';\nimport * as server from './server';\nimport * as parsers from './parsers';\nimport * as utils from './utils';\nimport { authenticatorMetadata } from './authenticatorMetadata'\n\nexport { client, server, parsers, utils, authenticatorMetadata }\n\nconst webauthn = { client, server, parsers, utils, authenticatorMetadata }\nexport default webauthn\n"], + "mappings": "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", + "names": ["client_exports", "__export", "authenticate", "isAutocompleteAvailable", "isAvailable", "isLocalAuthenticator", "register", "utils_exports", "__export", "bufferToHex", "concatenateBuffers", "isBase64url", "parseBase64url", "parseBuffer", "sha256", "toBase64url", "toBuffer", "txt", "c", "buffer", "b", "buffer1", "buffer2", "tmp", "isAvailable", "isLocalAuthenticator", "getAuthAttachment", "hints", "ongoingAuth", "register", "options", "isBase64url", "user", "creationOptions", "parseBase64url", "toBuffer", "raw", "response", "publicKey", "toBase64url", "isAutocompleteAvailable", "authenticate", "authOptions", "toPublicKeyCredentialDescriptor", "cred", "server_exports", "__export", "parseCryptoKey", "randomChallenge", "verifyAuthentication", "verifyRegistration", "verifySignature", "parsers_exports", "__export", "getAlgoName", "parseAuthentication", "parseAuthenticator", "parseClient", "parseRegistration", "toAuthenticationInfo", "toRegistrationInfo", "authenticatorMetadata", "utf8Decoder", "parseClient", "data", "parseBase64url", "parseAuthenticator", "authData", "flags", "extractRpIdHash", "extractAaguid", "toBase64url", "buffer", "hex", "bufferToHex", "getAlgoName", "num", "parseRegistration", "registrationJson", "authenticator", "toRegistrationInfo", "aaguid", "authenticatorMetadata", "toAuthenticationInfo", "authenticationJson", "parseAuthentication", "randomChallenge", "buffer", "toBase64url", "isValid", "validator", "value", "res", "isNotValid", "verifyRegistration", "registrationJson", "expected", "client", "parseClient", "authenticator", "parseAuthenticator", "parsers_exports", "verifyAuthentication", "authenticationJson", "credential", "verifySignature", "rpId", "expectedRpIdHash", "sha256", "toBuffer", "toAuthenticationInfo", "getAlgoParams", "algorithm", "parseCryptoKey", "publicKey", "algoParams", "parseBase64url", "authenticatorData", "clientData", "signature", "verbose", "cryptoKey", "clientHash", "comboBuffer", "concatenateBuffers", "signatureBuffer", "convertASN1toRaw", "rStart", "rEnd", "sStart", "r", "s", "webauthn", "client_exports", "server_exports", "parsers_exports", "utils_exports", "authenticatorMetadata", "src_default"] } diff --git a/docs/demos/playground.html b/docs/demos/playground.html index eb5fdcb..944b01b 100644 --- a/docs/demos/playground.html +++ b/docs/demos/playground.html @@ -243,19 +243,22 @@

Signature validation

-
The public key created during registration.
+
+

The public key created during registration.

+

Verify public key

+

-
{{parseAuthData(verification.authenticatorData)}}
+
{{parsedAuthData}}
-
{{parseClientData(verification.clientData)}}
+
{{parsedClientData}}
diff --git a/package.json b/package.json index a51f447..218146d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@passwordless-id/webauthn", - "version": "2.1.1", + "version": "2.1.2", "description": "A small wrapper around the webauthn protocol to make one's life easier.", "type": "module", @@ -14,8 +14,8 @@ "scripts": { "build": "npm run build-module && npm run build-nodejs && npm run build-browser && npm run build-demos", "build-module": "tsc", - "build-nodejs": "esbuild src/index.ts --platform=node --bundle --banner:js=/*passwordless-id/webauthn@2.1.1*/ --outfile=dist/cjs/webauthn.cjs", - "build-browser": "esbuild src/index.ts --platform=browser --bundle --banner:js=/*passwordless-id/webauthn@2.1.1*/ --format=esm --minify --sourcemap --outfile=dist/browser/webauthn.min.js", + "build-nodejs": "esbuild src/index.ts --platform=node --bundle --banner:js=/*passwordless-id/webauthn@2.1.2*/ --outfile=dist/cjs/webauthn.cjs", + "build-browser": "esbuild src/index.ts --platform=browser --bundle --banner:js=/*passwordless-id/webauthn@2.1.2*/ --format=esm --minify --sourcemap --outfile=dist/browser/webauthn.min.js", "build-demos": "cp dist/browser/*.js docs/demos/js; cp dist/browser/*.js.map docs/demos/js", "test": "jest", "dev": "mkdocs serve" diff --git a/src/client.ts b/src/client.ts index 343e35a..833f09b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -171,7 +171,9 @@ export async function authenticate(options: AuthenticateOptions): Promise { +export async function parseCryptoKey(algorithm: NamedAlgo, publicKey: string): Promise { + const algoParams = getAlgoParams(algorithm) const buffer = utils.parseBase64url(publicKey) return crypto.subtle.importKey('spki', buffer, algoParams, false, ['verify']) } @@ -180,8 +181,7 @@ type VerifyParams = { */ // see also https://gist.github.com/philholden/50120652bfe0498958fd5926694ba354 export async function verifySignature({ algorithm, publicKey, authenticatorData, clientData, signature, verbose }: VerifyParams): Promise { - const algoParams = getAlgoParams(algorithm) - let cryptoKey = await parseCryptoKey(algoParams, publicKey) + let cryptoKey = await parseCryptoKey(algorithm, publicKey) if(verbose) { console.debug(cryptoKey) @@ -193,7 +193,7 @@ export async function verifySignature({ algorithm, publicKey, authenticatorData, let comboBuffer = utils.concatenateBuffers(utils.parseBase64url(authenticatorData), clientHash) if(verbose) { - console.debug('Crypto Algo: ' + JSON.stringify(algoParams)) + console.debug('Algorithm: ' + algorithm) console.debug('Public key: ' + publicKey) console.debug('Data: ' + utils.toBase64url(comboBuffer)) console.debug('Signature: ' + signature) @@ -204,6 +204,7 @@ export async function verifySignature({ algorithm, publicKey, authenticatorData, if(algorithm == 'ES256') signatureBuffer = convertASN1toRaw(signatureBuffer) + const algoParams = getAlgoParams(algorithm) const isValid = await crypto.subtle.verify(algoParams, cryptoKey, signatureBuffer, comboBuffer) return isValid