2FAuth/public/build/assets/webauthnService-CpjBMhYF.js.map
2024-11-27 12:03:02 +01:00

1 line
25 KiB
Plaintext

{"version":3,"file":"webauthnService-CpjBMhYF.js","sources":["../../../resources/js/services/webauthn/webauthnAbortService.js","../../../resources/js/services/webauthn/isValidDomain.js","../../../resources/js/services/webauthn/identifyRegistrationError.js","../../../resources/js/services/webauthn/identifyAuthenticationError.js","../../../resources/js/services/webauthn/webauthnService.js"],"sourcesContent":["/**\n * MIT License\n *\n * Copyright (c) 2020 Matthew Miller - https://github.com/MasterKale/SimpleWebAuthn\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n * \n * A way to cancel an existing WebAuthn request, for example to cancel a\n * WebAuthn autofill authentication request for a manual authentication attempt.\n */\nclass WebauthnAbortService {\n controller;\n \n /**\n * Prepare an abort signal that will help support multiple auth attempts without needing to\n * reload the page\n */\n createNewAbortSignal() {\n // Abort any existing calls to navigator.credentials.create() or navigator.credentials.get()\n if (this.controller) {\n const abortError = new Error(\n 'Cancelling existing WebAuthn API call for new one',\n );\n abortError.name = 'AbortError';\n this.controller.abort(abortError);\n }\n\n const newController = new AbortController();\n\n this.controller = newController;\n return newController.signal;\n }\n}\n\nexport const webauthnAbortService = new WebauthnAbortService();","/**\n * A simple test to determine if a hostname is a properly-formatted domain name\n *\n * A \"valid domain\" is defined here: https://url.spec.whatwg.org/#valid-domain\n *\n * Regex sourced from here:\n * https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html\n */\nexport function isValidDomain(hostname) {\n return (\n // Consider localhost valid as well since it's okay wrt Secure Contexts\n hostname === 'localhost' ||\n /^([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,}$/i.test(hostname)\n );\n}","/**\n * MIT License\n *\n * Copyright (c) 2023 Bubka - https://github.com/Bubka/2FAuth\n * Copyright (c) 2020 Matthew Miller - https://github.com/MasterKale/SimpleWebAuthn\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n * \n */\n\nimport { isValidDomain } from './isValidDomain';\n\n/**\n * Attempt to intuit _why_ an error was raised after calling `navigator.credentials.create()`\n */\nexport function identifyRegistrationError(error, options) {\n const { publicKey } = options;\n\n if (error.name === 'AbortError') {\n if (options.signal instanceof AbortSignal) {\n // Registration ceremony was sent an abort signal\n // https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 16)\n\n return {\n phrase: 'errors.aborted_by_user',\n type: 'is-warning'\n }\n }\n\n } else if (error.name === 'ConstraintError') {\n if (publicKey.authenticatorSelection?.requireResidentKey === true) {\n // Discoverable credentials were required but no available authenticator supported it\n // https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 4)\n \n return {\n phrase: 'errors.authenticator_missing_discoverable_credential_support',\n type: 'is-danger'\n }\n\n } else if (publicKey.authenticatorSelection?.userVerification === 'required') {\n // User verification was required but no available authenticator supported it\n // https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 5)\n\n return {\n phrase: 'errors.authenticator_missing_user_verification_support',\n type: 'is-danger'\n }\n }\n\n } else if (error.name === 'InvalidStateError') {\n // The authenticator was previously registered\n // https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 20)\n // https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 3)\n \n return {\n phrase: 'errors.security_device_already_registered',\n type: 'is-danger'\n }\n\n } else if (error.name === 'NotAllowedError') {\n /**\n * Pass the error directly through. Platforms are overloading this error beyond what the spec\n * defines and we don't want to overwrite potentially useful error messages.\n */\n\n return {\n phrase: 'errors.not_allowed_operation',\n type: 'is-danger'\n }\n \n } else if (error.name === 'NotSupportedError') {\n\n const validPubKeyCredParams = publicKey.pubKeyCredParams.filter(\n (param) => param.type === 'public-key',\n );\n\n if (validPubKeyCredParams.length === 0) {\n // No entry in pubKeyCredParams was of type \"public-key\"\n // https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 10)\n\n return {\n phrase: 'errors.no_entry_was_of_type_public_key',\n type: 'is-danger'\n }\n }\n\n // No available authenticator supported any of the specified pubKeyCredParams algorithms\n // https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 2)\n\n return {\n phrase: 'errors.no_authenticator_support_specified_algorithms',\n type: 'is-danger'\n }\n\n } else if (error.name === 'SecurityError') {\n\n const effectiveDomain = window.location.hostname;\n\n if (!isValidDomain(effectiveDomain)) {\n // The current location domain is not a valid domain\n // https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 7)\n\n return {\n phrase: 'errors.2fauth_has_not_a_valid_domain',\n type: 'is-danger'\n }\n\n } else if (publicKey.rp.id !== effectiveDomain) {\n // The RP ID \"${publicKey.rp.id}\" is invalid for this domain\n // https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 8)\n\n return {\n phrase: 'errors.security_error_check_rpid',\n type: 'is-danger'\n }\n }\n\n } else if (error.name === 'TypeError') {\n if (publicKey.user.id.byteLength < 1 || publicKey.user.id.byteLength > 64) {\n // User ID was not between 1 and 64 characters\n // https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 5)\n\n return {\n phrase: 'errors.user_id_not_between_1_64',\n type: 'is-danger'\n }\n }\n\n } else if (error.name === 'UnknownError') {\n // The authenticator was unable to process the specified options, or could not create a new credential\n // https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 1)\n // https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 8)\n\n return {\n phrase: 'errors.unknown_error',\n type: 'is-danger'\n }\n }\n\n return {\n phrase: 'errors.unknown_error',\n type: 'is-danger'\n }\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023 Bubka - https://github.com/Bubka/2FAuth\n * Copyright (c) 2020 Matthew Miller - https://github.com/MasterKale/SimpleWebAuthn\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n * \n */\n\nimport { isValidDomain } from './isValidDomain';\n\n/**\n * Attempt to intuit _why_ an error was raised after calling `navigator.credentials.get()`\n */\nexport function identifyAuthenticationError(error, options) {\n const { publicKey } = options;\n\n if (error.name === 'AbortError') {\n if (options.signal instanceof AbortSignal) {\n // Authentication ceremony was sent an abort signal\n // https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 16)\n\n return {\n phrase: 'errors.aborted_by_user',\n type: 'is-warning'\n }\n }\n\n } else if (error.name === 'NotAllowedError') {\n /**\n * Pass the error directly through. Platforms are overloading this error beyond what the spec\n * defines and we don't want to overwrite potentially useful error messages.\n */\n\n return {\n phrase: 'errors.not_allowed_operation',\n type: 'is-danger'\n }\n\n } else if (error.name === 'SecurityError') {\n\n const effectiveDomain = window.location.hostname;\n\n if (!isValidDomain(effectiveDomain)) {\n // The current location domain is not a valid domain\n // https://www.w3.org/TR/webauthn-2/#sctn-discover-from-external-source (Step 5)\n\n return {\n phrase: 'errors.2fauth_has_not_a_valid_domain',\n type: 'is-danger'\n }\n\n } else if (publicKey.rpId !== effectiveDomain) {\n // The RP ID \"${publicKey.rpId}\" is invalid for this domain\n // // https://www.w3.org/TR/webauthn-2/#sctn-discover-from-external-source (Step 6)\n\n return {\n phrase: 'errors.security_error_check_rpid',\n type: 'is-danger'\n }\n }\n\n } else if (error.name === 'UnknownError') {\n // The authenticator was unable to process the specified options, or could not create a new assertion signature\n // https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion (Step 1)\n // https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion (Step 12)\n\n return {\n phrase: 'errors.unknown_error',\n type: 'is-danger'\n }\n }\n\n return {\n phrase: 'errors.unknown_error',\n type: 'is-danger'\n }\n}","/**\n * MIT License\n *\n * Copyright (c) 2023 Bubka - https://github.com/Bubka/2FAuth\n * Copyright (c) Italo Israel Baeza Cabrera - https://github.com/Laragear/WebAuthn\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { httpClientFactory } from '@/services/httpClientFactory'\nimport { webauthnAbortService } from '@/services/webauthn/webauthnAbortService'\nimport { identifyRegistrationError } from '@/services/webauthn/identifyRegistrationError'\nimport { identifyAuthenticationError } from '@/services/webauthn/identifyAuthenticationError'\n\nconst webClient = httpClientFactory('web')\n\nclass WebauthnService {\n\n async register() {\n let err = {\n webauthn: true,\n type: 'is-danger',\n message: ''\n }\n\n // Check https context\n if (!window.isSecureContext) {\n err.message = 'errors.https_required'\n return Promise.reject(err)\n }\n\n // Check browser support\n if (! WebauthnService.supportsWebAuthn) {\n err.message = 'errors.browser_does_not_support_webauthn'\n return Promise.reject(err)\n }\n\n const registerOptions = await webClient.post('/webauthn/register/options').then(response => response.data)\n const publicKey = WebauthnService.parseIncomingServerOptions(registerOptions)\n \n let options = { publicKey }\n options.signal = webauthnAbortService.createNewAbortSignal()\n\n let bufferedCredentials\n try {\n bufferedCredentials = await navigator.credentials.create(options)\n }\n catch (error) {\n const webauthnError = identifyRegistrationError(error, options)\n return Promise.reject({\n webauthn: true,\n type: webauthnError.type,\n message: webauthnError.phrase\n })\n }\n\n const publicKeyCredential = WebauthnService.parseOutgoingCredentials(bufferedCredentials);\n\n return webClient.post('/webauthn/register', publicKeyCredential, {returnError: true})\n }\n\n\n async authenticate(email) {\n\n // Check https context\n if (!window.isSecureContext) {\n err.message = 'errors.https_required'\n return Promise.reject(err)\n }\n\n // Check browser support\n if (! WebauthnService.supportsWebAuthn) {\n err.message = 'errors.browser_does_not_support_webauthn'\n return Promise.reject(err)\n }\n\n const loginOptions = await webClient.post('/webauthn/login/options', { email: email }).then(response => response.data)\n const publicKey = WebauthnService.parseIncomingServerOptions(loginOptions)\n\n let options = { publicKey }\n options.signal = webauthnAbortService.createNewAbortSignal()\n\n const credentials = await navigator.credentials.get(options)\n .catch(error => {\n const webauthnError = identifyAuthenticationError(error, options)\n return Promise.reject({\n webauthn: true,\n type: webauthnError.type,\n message: webauthnError.phrase\n })\n })\n\n let publicKeyCredential = WebauthnService.parseOutgoingCredentials(credentials)\n publicKeyCredential.email = email\n\n return webClient.post('/webauthn/login', publicKeyCredential, {returnError: true})\n }\n\n /**\n * Parses the Public Key Options received from the Server for the browser.\n *\n * @param publicKey {Object}\n * @returns {Object}\n */\n static parseIncomingServerOptions(publicKey) {\n publicKey.challenge = WebauthnService.uint8Array(publicKey.challenge);\n\n if ('user' in publicKey) {\n publicKey.user = {\n ...publicKey.user,\n id: WebauthnService.uint8Array(publicKey.user.id)\n };\n }\n\n [\n \"excludeCredentials\",\n \"allowCredentials\"\n ]\n .filter(key => key in publicKey)\n .forEach(key => {\n publicKey[key] = publicKey[key].map(data => {\n return {...data, id: WebauthnService.uint8Array(data.id)};\n });\n });\n\n return publicKey;\n }\n\n /**\n * Parses the outgoing credentials from the browser to the server.\n *\n * @param credentials {Credential|PublicKeyCredential}\n * @return {{response: {string}, rawId: string, id: string, type: string}}\n */\n static parseOutgoingCredentials(credentials) {\n let parseCredentials = {\n id: credentials.id,\n type: credentials.type,\n rawId: WebauthnService.arrayToBase64String(credentials.rawId),\n response: {}\n };\n\n [\n \"clientDataJSON\",\n \"attestationObject\",\n \"authenticatorData\",\n \"signature\",\n \"userHandle\"\n ]\n .filter(key => key in credentials.response)\n .forEach(key => parseCredentials.response[key] = WebauthnService.arrayToBase64String(credentials.response[key]));\n\n return parseCredentials;\n }\n\n /**\n * Transform a string into Uint8Array instance.\n *\n * @param input {string}\n * @param useAtob {boolean}\n * @returns {Uint8Array}\n */\n static uint8Array(input, useAtob = false) {\n return Uint8Array.from(\n useAtob ? atob(input) : WebauthnService.base64UrlDecode(input), c => c.charCodeAt(0)\n );\n }\n\n /**\n * Encodes an array of bytes to a BASE64 URL string\n *\n * @param arrayBuffer {ArrayBuffer|Uint8Array}\n * @returns {string}\n */\n static arrayToBase64String(arrayBuffer) {\n return btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));\n }\n\n \n /**\n * Decodes a BASE64 URL string into a normal string.\n *\n * @param input {string}\n * @returns {string|Iterable}\n */\n static base64UrlDecode(input) {\n input = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\n const pad = input.length % 4;\n\n if (pad) {\n if (pad === 1) {\n throw new Error(\"InvalidLengthError: Input base64url string is the wrong length to determine padding\");\n }\n\n input += new Array(5 - pad).join(\"=\");\n }\n\n return atob(input);\n }\n\n\n /**\n * Checks if the browser supports WebAuthn.\n *\n * @returns {boolean}\n */\n static supportsWebAuthn() {\n return (window?.PublicKeyCredential !== undefined && typeof window.PublicKeyCredential === 'function');\n }\n \n\n /**\n * Checks if the browser doesn't support WebAuthn.\n *\n * @returns {boolean}\n */\n // static doesntSupportWebAuthn() {\n // return !WebauthnService.supportsWebAuthn();\n // }\n}\n\nexport const webauthnService = new WebauthnService();"],"names":["WebauthnAbortService","__publicField","abortError","newController","webauthnAbortService","isValidDomain","hostname","identifyRegistrationError","error","options","publicKey","_a","_b","param","effectiveDomain","identifyAuthenticationError","webClient","httpClientFactory","WebauthnService","err","registerOptions","response","bufferedCredentials","webauthnError","publicKeyCredential","email","loginOptions","credentials","key","data","parseCredentials","input","useAtob","c","arrayBuffer","pad","webauthnService"],"mappings":"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"}