@simplewebauthn/browser 9.0.1 → 11.0.0-alpha3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/index.es5.umd.min.js +2 -0
- package/esm/helpers/base64URLStringToBuffer.d.ts +9 -0
- package/esm/helpers/base64URLStringToBuffer.d.ts.map +1 -0
- package/esm/helpers/base64URLStringToBuffer.js +29 -0
- package/esm/helpers/browserSupportsWebAuthn.d.ts +8 -0
- package/esm/helpers/browserSupportsWebAuthn.d.ts.map +1 -0
- package/esm/helpers/browserSupportsWebAuthn.js +11 -0
- package/esm/helpers/browserSupportsWebAuthnAutofill.d.ts +9 -0
- package/esm/helpers/browserSupportsWebAuthnAutofill.d.ts.map +1 -0
- package/esm/helpers/browserSupportsWebAuthnAutofill.js +26 -0
- package/esm/helpers/bufferToBase64URLString.d.ts +8 -0
- package/esm/helpers/bufferToBase64URLString.d.ts.map +1 -0
- package/esm/helpers/bufferToBase64URLString.js +15 -0
- package/esm/helpers/identifyAuthenticationError.d.ts +9 -0
- package/esm/helpers/identifyAuthenticationError.d.ts.map +1 -0
- package/esm/helpers/identifyAuthenticationError.js +61 -0
- package/esm/helpers/identifyRegistrationError.d.ts +9 -0
- package/esm/helpers/identifyRegistrationError.d.ts.map +1 -0
- package/esm/helpers/identifyRegistrationError.js +126 -0
- package/esm/helpers/isValidDomain.d.ts +10 -0
- package/esm/helpers/isValidDomain.d.ts.map +1 -0
- package/esm/helpers/isValidDomain.js +14 -0
- package/esm/helpers/platformAuthenticatorIsAvailable.d.ts +8 -0
- package/esm/helpers/platformAuthenticatorIsAvailable.d.ts.map +1 -0
- package/esm/helpers/platformAuthenticatorIsAvailable.js +13 -0
- package/{dist/types → esm}/helpers/toAuthenticatorAttachment.d.ts +4 -0
- package/esm/helpers/toAuthenticatorAttachment.d.ts.map +1 -0
- package/esm/helpers/toAuthenticatorAttachment.js +13 -0
- package/esm/helpers/toPublicKeyCredentialDescriptor.d.ts +3 -0
- package/esm/helpers/toPublicKeyCredentialDescriptor.d.ts.map +1 -0
- package/esm/helpers/toPublicKeyCredentialDescriptor.js +14 -0
- package/esm/helpers/webAuthnAbortService.d.ts +14 -0
- package/esm/helpers/webAuthnAbortService.d.ts.map +1 -0
- package/esm/helpers/webAuthnAbortService.js +45 -0
- package/{dist/types → esm}/helpers/webAuthnError.d.ts +19 -1
- package/esm/helpers/webAuthnError.d.ts.map +1 -0
- package/esm/helpers/webAuthnError.js +31 -0
- package/esm/index.d.ts +16 -0
- package/esm/index.d.ts.map +1 -0
- package/{dist/types/index.d.ts → esm/index.js} +13 -10
- package/esm/methods/startAuthentication.d.ts +15 -0
- package/esm/methods/startAuthentication.d.ts.map +1 -0
- package/esm/methods/startAuthentication.js +89 -0
- package/esm/methods/startRegistration.d.ts +13 -0
- package/esm/methods/startRegistration.d.ts.map +1 -0
- package/esm/methods/startRegistration.js +115 -0
- package/esm/package.json +3 -0
- package/package.json +24 -29
- package/script/helpers/base64URLStringToBuffer.d.ts +9 -0
- package/script/helpers/base64URLStringToBuffer.d.ts.map +1 -0
- package/script/helpers/base64URLStringToBuffer.js +32 -0
- package/script/helpers/browserSupportsWebAuthn.d.ts +8 -0
- package/script/helpers/browserSupportsWebAuthn.d.ts.map +1 -0
- package/script/helpers/browserSupportsWebAuthn.js +15 -0
- package/script/helpers/browserSupportsWebAuthnAutofill.d.ts +9 -0
- package/script/helpers/browserSupportsWebAuthnAutofill.d.ts.map +1 -0
- package/script/helpers/browserSupportsWebAuthnAutofill.js +30 -0
- package/script/helpers/bufferToBase64URLString.d.ts +8 -0
- package/script/helpers/bufferToBase64URLString.d.ts.map +1 -0
- package/script/helpers/bufferToBase64URLString.js +18 -0
- package/script/helpers/identifyAuthenticationError.d.ts +9 -0
- package/script/helpers/identifyAuthenticationError.d.ts.map +1 -0
- package/script/helpers/identifyAuthenticationError.js +64 -0
- package/script/helpers/identifyRegistrationError.d.ts +9 -0
- package/script/helpers/identifyRegistrationError.d.ts.map +1 -0
- package/script/helpers/identifyRegistrationError.js +129 -0
- package/script/helpers/isValidDomain.d.ts +10 -0
- package/script/helpers/isValidDomain.d.ts.map +1 -0
- package/script/helpers/isValidDomain.js +17 -0
- package/script/helpers/platformAuthenticatorIsAvailable.d.ts +8 -0
- package/script/helpers/platformAuthenticatorIsAvailable.d.ts.map +1 -0
- package/script/helpers/platformAuthenticatorIsAvailable.js +16 -0
- package/script/helpers/toAuthenticatorAttachment.d.ts +6 -0
- package/script/helpers/toAuthenticatorAttachment.d.ts.map +1 -0
- package/script/helpers/toAuthenticatorAttachment.js +16 -0
- package/script/helpers/toPublicKeyCredentialDescriptor.d.ts +3 -0
- package/script/helpers/toPublicKeyCredentialDescriptor.d.ts.map +1 -0
- package/script/helpers/toPublicKeyCredentialDescriptor.js +17 -0
- package/script/helpers/webAuthnAbortService.d.ts +14 -0
- package/script/helpers/webAuthnAbortService.d.ts.map +1 -0
- package/script/helpers/webAuthnAbortService.js +48 -0
- package/script/helpers/webAuthnError.d.ts +28 -0
- package/script/helpers/webAuthnError.d.ts.map +1 -0
- package/script/helpers/webAuthnError.js +35 -0
- package/script/index.d.ts +16 -0
- package/script/index.d.ts.map +1 -0
- package/script/index.js +25 -0
- package/script/methods/startAuthentication.d.ts +15 -0
- package/script/methods/startAuthentication.d.ts.map +1 -0
- package/script/methods/startAuthentication.js +92 -0
- package/script/methods/startRegistration.d.ts +13 -0
- package/script/methods/startRegistration.d.ts.map +1 -0
- package/script/methods/startRegistration.js +118 -0
- package/script/package.json +3 -0
- package/dist/bundle/index.es5.umd.min.js +0 -2
- package/dist/bundle/index.js +0 -389
- package/dist/bundle/index.umd.min.js +0 -2
- package/dist/types/helpers/base64URLStringToBuffer.d.ts +0 -1
- package/dist/types/helpers/browserSupportsWebAuthn.d.ts +0 -1
- package/dist/types/helpers/browserSupportsWebAuthnAutofill.d.ts +0 -1
- package/dist/types/helpers/bufferToBase64URLString.d.ts +0 -1
- package/dist/types/helpers/bufferToUTF8String.d.ts +0 -1
- package/dist/types/helpers/identifyAuthenticationError.d.ts +0 -5
- package/dist/types/helpers/identifyRegistrationError.d.ts +0 -5
- package/dist/types/helpers/isValidDomain.d.ts +0 -1
- package/dist/types/helpers/platformAuthenticatorIsAvailable.d.ts +0 -1
- package/dist/types/helpers/toPublicKeyCredentialDescriptor.d.ts +0 -2
- package/dist/types/helpers/utf8StringToBuffer.d.ts +0 -1
- package/dist/types/helpers/webAuthnAbortService.d.ts +0 -7
- package/dist/types/methods/startAuthentication.d.ts +0 -2
- package/dist/types/methods/startRegistration.d.ts +0 -2
- package/jest-environment.js +0 -29
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startRegistration = startRegistration;
|
|
4
|
+
const bufferToBase64URLString_js_1 = require("../helpers/bufferToBase64URLString.js");
|
|
5
|
+
const base64URLStringToBuffer_js_1 = require("../helpers/base64URLStringToBuffer.js");
|
|
6
|
+
const browserSupportsWebAuthn_js_1 = require("../helpers/browserSupportsWebAuthn.js");
|
|
7
|
+
const toPublicKeyCredentialDescriptor_js_1 = require("../helpers/toPublicKeyCredentialDescriptor.js");
|
|
8
|
+
const identifyRegistrationError_js_1 = require("../helpers/identifyRegistrationError.js");
|
|
9
|
+
const webAuthnAbortService_js_1 = require("../helpers/webAuthnAbortService.js");
|
|
10
|
+
const toAuthenticatorAttachment_js_1 = require("../helpers/toAuthenticatorAttachment.js");
|
|
11
|
+
/**
|
|
12
|
+
* Begin authenticator "registration" via WebAuthn attestation
|
|
13
|
+
*
|
|
14
|
+
* @param optionsJSON Output from **@simplewebauthn/server**'s `generateRegistrationOptions()`
|
|
15
|
+
* @param useAutoRegister (Optional) Try to silently create a passkey with the password manager that the user just signed in with. Defaults to `false`.
|
|
16
|
+
*/
|
|
17
|
+
async function startRegistration(options) {
|
|
18
|
+
const { optionsJSON, useAutoRegister = false } = options;
|
|
19
|
+
if (!(0, browserSupportsWebAuthn_js_1.browserSupportsWebAuthn)()) {
|
|
20
|
+
throw new Error('WebAuthn is not supported in this browser');
|
|
21
|
+
}
|
|
22
|
+
// We need to convert some values to Uint8Arrays before passing the credentials to the navigator
|
|
23
|
+
const publicKey = {
|
|
24
|
+
...optionsJSON,
|
|
25
|
+
challenge: (0, base64URLStringToBuffer_js_1.base64URLStringToBuffer)(optionsJSON.challenge),
|
|
26
|
+
user: {
|
|
27
|
+
...optionsJSON.user,
|
|
28
|
+
id: (0, base64URLStringToBuffer_js_1.base64URLStringToBuffer)(optionsJSON.user.id),
|
|
29
|
+
},
|
|
30
|
+
excludeCredentials: optionsJSON.excludeCredentials?.map(toPublicKeyCredentialDescriptor_js_1.toPublicKeyCredentialDescriptor),
|
|
31
|
+
};
|
|
32
|
+
// Prepare options for `.create()`
|
|
33
|
+
const createOptions = {};
|
|
34
|
+
/**
|
|
35
|
+
* Try to use conditional create to register a passkey for the user with the password manager
|
|
36
|
+
* the user just used to authenticate with. The user won't be shown any prominent UI by the
|
|
37
|
+
* browser.
|
|
38
|
+
*/
|
|
39
|
+
if (useAutoRegister) {
|
|
40
|
+
// @ts-ignore: `mediation` doesn't yet exist on CredentialCreationOptions but it's possible as of Sept 2024
|
|
41
|
+
createOptions.mediation = 'conditional';
|
|
42
|
+
}
|
|
43
|
+
// Finalize options
|
|
44
|
+
createOptions.publicKey = publicKey;
|
|
45
|
+
// Set up the ability to cancel this request if the user attempts another
|
|
46
|
+
createOptions.signal = webAuthnAbortService_js_1.WebAuthnAbortService.createNewAbortSignal();
|
|
47
|
+
// Wait for the user to complete attestation
|
|
48
|
+
let credential;
|
|
49
|
+
try {
|
|
50
|
+
credential = (await navigator.credentials.create(createOptions));
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
throw (0, identifyRegistrationError_js_1.identifyRegistrationError)({ error: err, options: createOptions });
|
|
54
|
+
}
|
|
55
|
+
if (!credential) {
|
|
56
|
+
throw new Error('Registration was not completed');
|
|
57
|
+
}
|
|
58
|
+
const { id, rawId, response, type } = credential;
|
|
59
|
+
// Continue to play it safe with `getTransports()` for now, even when L3 types say it's required
|
|
60
|
+
let transports = undefined;
|
|
61
|
+
if (typeof response.getTransports === 'function') {
|
|
62
|
+
transports = response.getTransports();
|
|
63
|
+
}
|
|
64
|
+
// L3 says this is required, but browser and webview support are still not guaranteed.
|
|
65
|
+
let responsePublicKeyAlgorithm = undefined;
|
|
66
|
+
if (typeof response.getPublicKeyAlgorithm === 'function') {
|
|
67
|
+
try {
|
|
68
|
+
responsePublicKeyAlgorithm = response.getPublicKeyAlgorithm();
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
warnOnBrokenImplementation('getPublicKeyAlgorithm()', error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
let responsePublicKey = undefined;
|
|
75
|
+
if (typeof response.getPublicKey === 'function') {
|
|
76
|
+
try {
|
|
77
|
+
const _publicKey = response.getPublicKey();
|
|
78
|
+
if (_publicKey !== null) {
|
|
79
|
+
responsePublicKey = (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(_publicKey);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
warnOnBrokenImplementation('getPublicKey()', error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// L3 says this is required, but browser and webview support are still not guaranteed.
|
|
87
|
+
let responseAuthenticatorData;
|
|
88
|
+
if (typeof response.getAuthenticatorData === 'function') {
|
|
89
|
+
try {
|
|
90
|
+
responseAuthenticatorData = (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(response.getAuthenticatorData());
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
warnOnBrokenImplementation('getAuthenticatorData()', error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
id,
|
|
98
|
+
rawId: (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(rawId),
|
|
99
|
+
response: {
|
|
100
|
+
attestationObject: (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(response.attestationObject),
|
|
101
|
+
clientDataJSON: (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(response.clientDataJSON),
|
|
102
|
+
transports,
|
|
103
|
+
publicKeyAlgorithm: responsePublicKeyAlgorithm,
|
|
104
|
+
publicKey: responsePublicKey,
|
|
105
|
+
authenticatorData: responseAuthenticatorData,
|
|
106
|
+
},
|
|
107
|
+
type,
|
|
108
|
+
clientExtensionResults: credential.getClientExtensionResults(),
|
|
109
|
+
authenticatorAttachment: (0, toAuthenticatorAttachment_js_1.toAuthenticatorAttachment)(credential.authenticatorAttachment),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Visibly warn when we detect an issue related to a passkey provider intercepting WebAuthn API
|
|
114
|
+
* calls
|
|
115
|
+
*/
|
|
116
|
+
function warnOnBrokenImplementation(methodName, cause) {
|
|
117
|
+
console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${methodName}. You should report this error to them.\n`, cause);
|
|
118
|
+
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/* [@simplewebauthn/browser@9.0.1] */
|
|
2
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).SimpleWebAuthnBrowser={})}(this,(function(e){"use strict";var t=function(e,r){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},t(e,r)};var r=function(){return r=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var o in t=arguments[r])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},r.apply(this,arguments)};function n(e,t,r,n){return new(r||(r=Promise))((function(o,i){function a(e){try{c(n.next(e))}catch(e){i(e)}}function s(e){try{c(n.throw(e))}catch(e){i(e)}}function c(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(a,s)}c((n=n.apply(e,t||[])).next())}))}function o(e,t){var r,n,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(s){return function(c){return function(s){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,s[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&s[0]?n.return:s[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,s[1])).done)return o;switch(n=0,o&&(s=[2&s[0],o.value]),s[0]){case 0:case 1:o=s;break;case 4:return a.label++,{value:s[1],done:!1};case 5:a.label++,n=s[1],s=[0];continue;case 7:s=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]<o[3])){a.label=s[1];break}if(6===s[0]&&a.label<o[1]){a.label=o[1],o=s;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(s);break}o[2]&&a.ops.pop(),a.trys.pop();continue}s=t.call(e,a)}catch(e){s=[6,e],n=0}finally{r=o=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,c])}}}function i(e){var t,r,n=new Uint8Array(e),o="";try{for(var i=function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}(n),a=i.next();!a.done;a=i.next()){var s=a.value;o+=String.fromCharCode(s)}}catch(e){t={error:e}}finally{try{a&&!a.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return btoa(o).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function a(e){for(var t=e.replace(/-/g,"+").replace(/_/g,"/"),r=(4-t.length%4)%4,n=t.padEnd(t.length+r,"="),o=atob(n),i=new ArrayBuffer(o.length),a=new Uint8Array(i),s=0;s<o.length;s++)a[s]=o.charCodeAt(s);return i}function s(){return void 0!==(null===window||void 0===window?void 0:window.PublicKeyCredential)&&"function"==typeof window.PublicKeyCredential}function c(e){var t=e.id;return r(r({},e),{id:a(t),transports:e.transports})}function u(e){return"localhost"===e||/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(e)}"function"==typeof SuppressedError&&SuppressedError;var l=function(e){function r(t){var r=t.message,n=t.code,o=t.cause,i=t.name,a=e.call(this,r,{cause:o})||this;return a.name=null!=i?i:o.name,a.code=n,a}return function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function n(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}(r,e),r}(Error);var d=new(function(){function e(){}return e.prototype.createNewAbortSignal=function(){if(this.controller){var e=new Error("Cancelling existing WebAuthn API call for new one");e.name="AbortError",this.controller.abort(e)}var t=new AbortController;return this.controller=t,t.signal},e.prototype.cancelCeremony=function(){if(this.controller){var e=new Error("Manually cancelling existing WebAuthn API call");e.name="AbortError",this.controller.abort(e),this.controller=void 0}},e}()),f=["cross-platform","platform"];function p(e){if(e&&!(f.indexOf(e)<0))return e}function h(e,t){console.warn("The browser extension that intercepted this WebAuthn API call incorrectly implemented ".concat(e,". You should report this error to them.\n"),t)}function w(){var e=window.PublicKeyCredential;return void 0===e.isConditionalMediationAvailable?new Promise((function(e){return e(!1)})):e.isConditionalMediationAvailable()}e.WebAuthnAbortService=d,e.WebAuthnError=l,e.base64URLStringToBuffer=a,e.browserSupportsWebAuthn=s,e.browserSupportsWebAuthnAutofill=w,e.bufferToBase64URLString=i,e.platformAuthenticatorIsAvailable=function(){return s()?PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable():new Promise((function(e){return e(!1)}))},e.startAuthentication=function(e,t){var f,h;return void 0===t&&(t=!1),n(this,void 0,void 0,(function(){var n,b,y,R,g,E,A,m,v;return o(this,(function(o){switch(o.label){case 0:if(!s())throw new Error("WebAuthn is not supported in this browser");return 0!==(null===(f=e.allowCredentials)||void 0===f?void 0:f.length)&&(n=null===(h=e.allowCredentials)||void 0===h?void 0:h.map(c)),b=r(r({},e),{challenge:a(e.challenge),allowCredentials:n}),y={},t?[4,w()]:[3,2];case 1:if(!o.sent())throw Error("Browser does not support WebAuthn autofill");if(document.querySelectorAll("input[autocomplete$='webauthn']").length<1)throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');y.mediation="conditional",b.allowCredentials=[],o.label=2;case 2:y.publicKey=b,y.signal=d.createNewAbortSignal(),o.label=3;case 3:return o.trys.push([3,5,,6]),[4,navigator.credentials.get(y)];case 4:return R=o.sent(),[3,6];case 5:throw function(e){var t=e.error,r=e.options,n=r.publicKey;if(!n)throw Error("options was missing required publicKey property");if("AbortError"===t.name){if(r.signal instanceof AbortSignal)return new l({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:t})}else{if("NotAllowedError"===t.name)return new l({message:t.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:t});if("SecurityError"===t.name){var o=window.location.hostname;if(!u(o))return new l({message:"".concat(window.location.hostname," is an invalid domain"),code:"ERROR_INVALID_DOMAIN",cause:t});if(n.rpId!==o)return new l({message:'The RP ID "'.concat(n.rpId,'" is invalid for this domain'),code:"ERROR_INVALID_RP_ID",cause:t})}else if("UnknownError"===t.name)return new l({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:t})}return t}({error:o.sent(),options:y});case 6:if(!R)throw new Error("Authentication was not completed");return g=R.id,E=R.rawId,A=R.response,m=R.type,v=void 0,A.userHandle&&(_=A.userHandle,v=new TextDecoder("utf-8").decode(_)),[2,{id:g,rawId:i(E),response:{authenticatorData:i(A.authenticatorData),clientDataJSON:i(A.clientDataJSON),signature:i(A.signature),userHandle:v},type:m,clientExtensionResults:R.getClientExtensionResults(),authenticatorAttachment:p(R.authenticatorAttachment)}]}var _}))}))},e.startRegistration=function(e){var t;return n(this,void 0,void 0,(function(){var n,f,w,b,y,R,g,E,A,m,v,_;return o(this,(function(o){switch(o.label){case 0:if(!s())throw new Error("WebAuthn is not supported in this browser");n=r(r({},e),{challenge:a(e.challenge),user:r(r({},e.user),{id:(O=e.user.id,(new TextEncoder).encode(O))}),excludeCredentials:null===(t=e.excludeCredentials)||void 0===t?void 0:t.map(c)}),(f={publicKey:n}).signal=d.createNewAbortSignal(),o.label=1;case 1:return o.trys.push([1,3,,4]),[4,navigator.credentials.create(f)];case 2:return w=o.sent(),[3,4];case 3:throw function(e){var t,r,n=e.error,o=e.options,i=o.publicKey;if(!i)throw Error("options was missing required publicKey property");if("AbortError"===n.name){if(o.signal instanceof AbortSignal)return new l({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:n})}else if("ConstraintError"===n.name){if(!0===(null===(t=i.authenticatorSelection)||void 0===t?void 0:t.requireResidentKey))return new l({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:n});if("required"===(null===(r=i.authenticatorSelection)||void 0===r?void 0:r.userVerification))return new l({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:n})}else{if("InvalidStateError"===n.name)return new l({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:n});if("NotAllowedError"===n.name)return new l({message:n.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:n});if("NotSupportedError"===n.name)return 0===i.pubKeyCredParams.filter((function(e){return"public-key"===e.type})).length?new l({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:n}):new l({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:n});if("SecurityError"===n.name){var a=window.location.hostname;if(!u(a))return new l({message:"".concat(window.location.hostname," is an invalid domain"),code:"ERROR_INVALID_DOMAIN",cause:n});if(i.rp.id!==a)return new l({message:'The RP ID "'.concat(i.rp.id,'" is invalid for this domain'),code:"ERROR_INVALID_RP_ID",cause:n})}else if("TypeError"===n.name){if(i.user.id.byteLength<1||i.user.id.byteLength>64)return new l({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:n})}else if("UnknownError"===n.name)return new l({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:n})}return n}({error:o.sent(),options:f});case 4:if(!w)throw new Error("Registration was not completed");if(b=w.id,y=w.rawId,R=w.response,g=w.type,E=void 0,"function"==typeof R.getTransports&&(E=R.getTransports()),A=void 0,"function"==typeof R.getPublicKeyAlgorithm)try{A=R.getPublicKeyAlgorithm()}catch(e){h("getPublicKeyAlgorithm()",e)}if(m=void 0,"function"==typeof R.getPublicKey)try{null!==(v=R.getPublicKey())&&(m=i(v))}catch(e){h("getPublicKey()",e)}if("function"==typeof R.getAuthenticatorData)try{_=i(R.getAuthenticatorData())}catch(e){h("getAuthenticatorData()",e)}return[2,{id:b,rawId:i(y),response:{attestationObject:i(R.attestationObject),clientDataJSON:i(R.clientDataJSON),transports:E,publicKeyAlgorithm:A,publicKey:m,authenticatorData:_},type:g,clientExtensionResults:w.getClientExtensionResults(),authenticatorAttachment:p(w.authenticatorAttachment)}]}var O}))}))},Object.defineProperty(e,"__esModule",{value:!0})}));
|
package/dist/bundle/index.js
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
/* [@simplewebauthn/browser@9.0.1] */
|
|
2
|
-
function utf8StringToBuffer(value) {
|
|
3
|
-
return new TextEncoder().encode(value);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
function bufferToBase64URLString(buffer) {
|
|
7
|
-
const bytes = new Uint8Array(buffer);
|
|
8
|
-
let str = '';
|
|
9
|
-
for (const charCode of bytes) {
|
|
10
|
-
str += String.fromCharCode(charCode);
|
|
11
|
-
}
|
|
12
|
-
const base64String = btoa(str);
|
|
13
|
-
return base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function base64URLStringToBuffer(base64URLString) {
|
|
17
|
-
const base64 = base64URLString.replace(/-/g, '+').replace(/_/g, '/');
|
|
18
|
-
const padLength = (4 - (base64.length % 4)) % 4;
|
|
19
|
-
const padded = base64.padEnd(base64.length + padLength, '=');
|
|
20
|
-
const binary = atob(padded);
|
|
21
|
-
const buffer = new ArrayBuffer(binary.length);
|
|
22
|
-
const bytes = new Uint8Array(buffer);
|
|
23
|
-
for (let i = 0; i < binary.length; i++) {
|
|
24
|
-
bytes[i] = binary.charCodeAt(i);
|
|
25
|
-
}
|
|
26
|
-
return buffer;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function browserSupportsWebAuthn() {
|
|
30
|
-
return (window?.PublicKeyCredential !== undefined &&
|
|
31
|
-
typeof window.PublicKeyCredential === 'function');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function toPublicKeyCredentialDescriptor(descriptor) {
|
|
35
|
-
const { id } = descriptor;
|
|
36
|
-
return {
|
|
37
|
-
...descriptor,
|
|
38
|
-
id: base64URLStringToBuffer(id),
|
|
39
|
-
transports: descriptor.transports,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function isValidDomain(hostname) {
|
|
44
|
-
return (hostname === 'localhost' ||
|
|
45
|
-
/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(hostname));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
class WebAuthnError extends Error {
|
|
49
|
-
constructor({ message, code, cause, name, }) {
|
|
50
|
-
super(message, { cause });
|
|
51
|
-
this.name = name ?? cause.name;
|
|
52
|
-
this.code = code;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function identifyRegistrationError({ error, options, }) {
|
|
57
|
-
const { publicKey } = options;
|
|
58
|
-
if (!publicKey) {
|
|
59
|
-
throw Error('options was missing required publicKey property');
|
|
60
|
-
}
|
|
61
|
-
if (error.name === 'AbortError') {
|
|
62
|
-
if (options.signal instanceof AbortSignal) {
|
|
63
|
-
return new WebAuthnError({
|
|
64
|
-
message: 'Registration ceremony was sent an abort signal',
|
|
65
|
-
code: 'ERROR_CEREMONY_ABORTED',
|
|
66
|
-
cause: error,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
else if (error.name === 'ConstraintError') {
|
|
71
|
-
if (publicKey.authenticatorSelection?.requireResidentKey === true) {
|
|
72
|
-
return new WebAuthnError({
|
|
73
|
-
message: 'Discoverable credentials were required but no available authenticator supported it',
|
|
74
|
-
code: 'ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT',
|
|
75
|
-
cause: error,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
else if (publicKey.authenticatorSelection?.userVerification === 'required') {
|
|
79
|
-
return new WebAuthnError({
|
|
80
|
-
message: 'User verification was required but no available authenticator supported it',
|
|
81
|
-
code: 'ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT',
|
|
82
|
-
cause: error,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
else if (error.name === 'InvalidStateError') {
|
|
87
|
-
return new WebAuthnError({
|
|
88
|
-
message: 'The authenticator was previously registered',
|
|
89
|
-
code: 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED',
|
|
90
|
-
cause: error,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
else if (error.name === 'NotAllowedError') {
|
|
94
|
-
return new WebAuthnError({
|
|
95
|
-
message: error.message,
|
|
96
|
-
code: 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY',
|
|
97
|
-
cause: error,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
else if (error.name === 'NotSupportedError') {
|
|
101
|
-
const validPubKeyCredParams = publicKey.pubKeyCredParams.filter((param) => param.type === 'public-key');
|
|
102
|
-
if (validPubKeyCredParams.length === 0) {
|
|
103
|
-
return new WebAuthnError({
|
|
104
|
-
message: 'No entry in pubKeyCredParams was of type "public-key"',
|
|
105
|
-
code: 'ERROR_MALFORMED_PUBKEYCREDPARAMS',
|
|
106
|
-
cause: error,
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
return new WebAuthnError({
|
|
110
|
-
message: 'No available authenticator supported any of the specified pubKeyCredParams algorithms',
|
|
111
|
-
code: 'ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG',
|
|
112
|
-
cause: error,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
else if (error.name === 'SecurityError') {
|
|
116
|
-
const effectiveDomain = window.location.hostname;
|
|
117
|
-
if (!isValidDomain(effectiveDomain)) {
|
|
118
|
-
return new WebAuthnError({
|
|
119
|
-
message: `${window.location.hostname} is an invalid domain`,
|
|
120
|
-
code: 'ERROR_INVALID_DOMAIN',
|
|
121
|
-
cause: error,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
else if (publicKey.rp.id !== effectiveDomain) {
|
|
125
|
-
return new WebAuthnError({
|
|
126
|
-
message: `The RP ID "${publicKey.rp.id}" is invalid for this domain`,
|
|
127
|
-
code: 'ERROR_INVALID_RP_ID',
|
|
128
|
-
cause: error,
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
else if (error.name === 'TypeError') {
|
|
133
|
-
if (publicKey.user.id.byteLength < 1 || publicKey.user.id.byteLength > 64) {
|
|
134
|
-
return new WebAuthnError({
|
|
135
|
-
message: 'User ID was not between 1 and 64 characters',
|
|
136
|
-
code: 'ERROR_INVALID_USER_ID_LENGTH',
|
|
137
|
-
cause: error,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
else if (error.name === 'UnknownError') {
|
|
142
|
-
return new WebAuthnError({
|
|
143
|
-
message: 'The authenticator was unable to process the specified options, or could not create a new credential',
|
|
144
|
-
code: 'ERROR_AUTHENTICATOR_GENERAL_ERROR',
|
|
145
|
-
cause: error,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
return error;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
class BaseWebAuthnAbortService {
|
|
152
|
-
createNewAbortSignal() {
|
|
153
|
-
if (this.controller) {
|
|
154
|
-
const abortError = new Error('Cancelling existing WebAuthn API call for new one');
|
|
155
|
-
abortError.name = 'AbortError';
|
|
156
|
-
this.controller.abort(abortError);
|
|
157
|
-
}
|
|
158
|
-
const newController = new AbortController();
|
|
159
|
-
this.controller = newController;
|
|
160
|
-
return newController.signal;
|
|
161
|
-
}
|
|
162
|
-
cancelCeremony() {
|
|
163
|
-
if (this.controller) {
|
|
164
|
-
const abortError = new Error('Manually cancelling existing WebAuthn API call');
|
|
165
|
-
abortError.name = 'AbortError';
|
|
166
|
-
this.controller.abort(abortError);
|
|
167
|
-
this.controller = undefined;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
const WebAuthnAbortService = new BaseWebAuthnAbortService();
|
|
172
|
-
|
|
173
|
-
const attachments = ['cross-platform', 'platform'];
|
|
174
|
-
function toAuthenticatorAttachment(attachment) {
|
|
175
|
-
if (!attachment) {
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
if (attachments.indexOf(attachment) < 0) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
return attachment;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
async function startRegistration(creationOptionsJSON) {
|
|
185
|
-
if (!browserSupportsWebAuthn()) {
|
|
186
|
-
throw new Error('WebAuthn is not supported in this browser');
|
|
187
|
-
}
|
|
188
|
-
const publicKey = {
|
|
189
|
-
...creationOptionsJSON,
|
|
190
|
-
challenge: base64URLStringToBuffer(creationOptionsJSON.challenge),
|
|
191
|
-
user: {
|
|
192
|
-
...creationOptionsJSON.user,
|
|
193
|
-
id: utf8StringToBuffer(creationOptionsJSON.user.id),
|
|
194
|
-
},
|
|
195
|
-
excludeCredentials: creationOptionsJSON.excludeCredentials?.map(toPublicKeyCredentialDescriptor),
|
|
196
|
-
};
|
|
197
|
-
const options = { publicKey };
|
|
198
|
-
options.signal = WebAuthnAbortService.createNewAbortSignal();
|
|
199
|
-
let credential;
|
|
200
|
-
try {
|
|
201
|
-
credential = (await navigator.credentials.create(options));
|
|
202
|
-
}
|
|
203
|
-
catch (err) {
|
|
204
|
-
throw identifyRegistrationError({ error: err, options });
|
|
205
|
-
}
|
|
206
|
-
if (!credential) {
|
|
207
|
-
throw new Error('Registration was not completed');
|
|
208
|
-
}
|
|
209
|
-
const { id, rawId, response, type } = credential;
|
|
210
|
-
let transports = undefined;
|
|
211
|
-
if (typeof response.getTransports === 'function') {
|
|
212
|
-
transports = response.getTransports();
|
|
213
|
-
}
|
|
214
|
-
let responsePublicKeyAlgorithm = undefined;
|
|
215
|
-
if (typeof response.getPublicKeyAlgorithm === 'function') {
|
|
216
|
-
try {
|
|
217
|
-
responsePublicKeyAlgorithm = response.getPublicKeyAlgorithm();
|
|
218
|
-
}
|
|
219
|
-
catch (error) {
|
|
220
|
-
warnOnBrokenImplementation('getPublicKeyAlgorithm()', error);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
let responsePublicKey = undefined;
|
|
224
|
-
if (typeof response.getPublicKey === 'function') {
|
|
225
|
-
try {
|
|
226
|
-
const _publicKey = response.getPublicKey();
|
|
227
|
-
if (_publicKey !== null) {
|
|
228
|
-
responsePublicKey = bufferToBase64URLString(_publicKey);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
catch (error) {
|
|
232
|
-
warnOnBrokenImplementation('getPublicKey()', error);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
let responseAuthenticatorData;
|
|
236
|
-
if (typeof response.getAuthenticatorData === 'function') {
|
|
237
|
-
try {
|
|
238
|
-
responseAuthenticatorData = bufferToBase64URLString(response.getAuthenticatorData());
|
|
239
|
-
}
|
|
240
|
-
catch (error) {
|
|
241
|
-
warnOnBrokenImplementation('getAuthenticatorData()', error);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return {
|
|
245
|
-
id,
|
|
246
|
-
rawId: bufferToBase64URLString(rawId),
|
|
247
|
-
response: {
|
|
248
|
-
attestationObject: bufferToBase64URLString(response.attestationObject),
|
|
249
|
-
clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
|
|
250
|
-
transports,
|
|
251
|
-
publicKeyAlgorithm: responsePublicKeyAlgorithm,
|
|
252
|
-
publicKey: responsePublicKey,
|
|
253
|
-
authenticatorData: responseAuthenticatorData,
|
|
254
|
-
},
|
|
255
|
-
type,
|
|
256
|
-
clientExtensionResults: credential.getClientExtensionResults(),
|
|
257
|
-
authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment),
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
function warnOnBrokenImplementation(methodName, cause) {
|
|
261
|
-
console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${methodName}. You should report this error to them.\n`, cause);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function bufferToUTF8String(value) {
|
|
265
|
-
return new TextDecoder('utf-8').decode(value);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function browserSupportsWebAuthnAutofill() {
|
|
269
|
-
const globalPublicKeyCredential = window
|
|
270
|
-
.PublicKeyCredential;
|
|
271
|
-
if (globalPublicKeyCredential.isConditionalMediationAvailable === undefined) {
|
|
272
|
-
return new Promise((resolve) => resolve(false));
|
|
273
|
-
}
|
|
274
|
-
return globalPublicKeyCredential.isConditionalMediationAvailable();
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function identifyAuthenticationError({ error, options, }) {
|
|
278
|
-
const { publicKey } = options;
|
|
279
|
-
if (!publicKey) {
|
|
280
|
-
throw Error('options was missing required publicKey property');
|
|
281
|
-
}
|
|
282
|
-
if (error.name === 'AbortError') {
|
|
283
|
-
if (options.signal instanceof AbortSignal) {
|
|
284
|
-
return new WebAuthnError({
|
|
285
|
-
message: 'Authentication ceremony was sent an abort signal',
|
|
286
|
-
code: 'ERROR_CEREMONY_ABORTED',
|
|
287
|
-
cause: error,
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
else if (error.name === 'NotAllowedError') {
|
|
292
|
-
return new WebAuthnError({
|
|
293
|
-
message: error.message,
|
|
294
|
-
code: 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY',
|
|
295
|
-
cause: error,
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
else if (error.name === 'SecurityError') {
|
|
299
|
-
const effectiveDomain = window.location.hostname;
|
|
300
|
-
if (!isValidDomain(effectiveDomain)) {
|
|
301
|
-
return new WebAuthnError({
|
|
302
|
-
message: `${window.location.hostname} is an invalid domain`,
|
|
303
|
-
code: 'ERROR_INVALID_DOMAIN',
|
|
304
|
-
cause: error,
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
else if (publicKey.rpId !== effectiveDomain) {
|
|
308
|
-
return new WebAuthnError({
|
|
309
|
-
message: `The RP ID "${publicKey.rpId}" is invalid for this domain`,
|
|
310
|
-
code: 'ERROR_INVALID_RP_ID',
|
|
311
|
-
cause: error,
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
else if (error.name === 'UnknownError') {
|
|
316
|
-
return new WebAuthnError({
|
|
317
|
-
message: 'The authenticator was unable to process the specified options, or could not create a new assertion signature',
|
|
318
|
-
code: 'ERROR_AUTHENTICATOR_GENERAL_ERROR',
|
|
319
|
-
cause: error,
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
return error;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
async function startAuthentication(requestOptionsJSON, useBrowserAutofill = false) {
|
|
326
|
-
if (!browserSupportsWebAuthn()) {
|
|
327
|
-
throw new Error('WebAuthn is not supported in this browser');
|
|
328
|
-
}
|
|
329
|
-
let allowCredentials;
|
|
330
|
-
if (requestOptionsJSON.allowCredentials?.length !== 0) {
|
|
331
|
-
allowCredentials = requestOptionsJSON.allowCredentials?.map(toPublicKeyCredentialDescriptor);
|
|
332
|
-
}
|
|
333
|
-
const publicKey = {
|
|
334
|
-
...requestOptionsJSON,
|
|
335
|
-
challenge: base64URLStringToBuffer(requestOptionsJSON.challenge),
|
|
336
|
-
allowCredentials,
|
|
337
|
-
};
|
|
338
|
-
const options = {};
|
|
339
|
-
if (useBrowserAutofill) {
|
|
340
|
-
if (!(await browserSupportsWebAuthnAutofill())) {
|
|
341
|
-
throw Error('Browser does not support WebAuthn autofill');
|
|
342
|
-
}
|
|
343
|
-
const eligibleInputs = document.querySelectorAll('input[autocomplete$=\'webauthn\']');
|
|
344
|
-
if (eligibleInputs.length < 1) {
|
|
345
|
-
throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');
|
|
346
|
-
}
|
|
347
|
-
options.mediation = 'conditional';
|
|
348
|
-
publicKey.allowCredentials = [];
|
|
349
|
-
}
|
|
350
|
-
options.publicKey = publicKey;
|
|
351
|
-
options.signal = WebAuthnAbortService.createNewAbortSignal();
|
|
352
|
-
let credential;
|
|
353
|
-
try {
|
|
354
|
-
credential = (await navigator.credentials.get(options));
|
|
355
|
-
}
|
|
356
|
-
catch (err) {
|
|
357
|
-
throw identifyAuthenticationError({ error: err, options });
|
|
358
|
-
}
|
|
359
|
-
if (!credential) {
|
|
360
|
-
throw new Error('Authentication was not completed');
|
|
361
|
-
}
|
|
362
|
-
const { id, rawId, response, type } = credential;
|
|
363
|
-
let userHandle = undefined;
|
|
364
|
-
if (response.userHandle) {
|
|
365
|
-
userHandle = bufferToUTF8String(response.userHandle);
|
|
366
|
-
}
|
|
367
|
-
return {
|
|
368
|
-
id,
|
|
369
|
-
rawId: bufferToBase64URLString(rawId),
|
|
370
|
-
response: {
|
|
371
|
-
authenticatorData: bufferToBase64URLString(response.authenticatorData),
|
|
372
|
-
clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
|
|
373
|
-
signature: bufferToBase64URLString(response.signature),
|
|
374
|
-
userHandle,
|
|
375
|
-
},
|
|
376
|
-
type,
|
|
377
|
-
clientExtensionResults: credential.getClientExtensionResults(),
|
|
378
|
-
authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment),
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
function platformAuthenticatorIsAvailable() {
|
|
383
|
-
if (!browserSupportsWebAuthn()) {
|
|
384
|
-
return new Promise((resolve) => resolve(false));
|
|
385
|
-
}
|
|
386
|
-
return PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
export { WebAuthnAbortService, WebAuthnError, base64URLStringToBuffer, browserSupportsWebAuthn, browserSupportsWebAuthnAutofill, bufferToBase64URLString, platformAuthenticatorIsAvailable, startAuthentication, startRegistration };
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/* [@simplewebauthn/browser@9.0.1] */
|
|
2
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).SimpleWebAuthnBrowser={})}(this,(function(e){"use strict";function t(e){const t=new Uint8Array(e);let r="";for(const e of t)r+=String.fromCharCode(e);return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function r(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),r=(4-t.length%4)%4,n=t.padEnd(t.length+r,"="),o=atob(n),a=new ArrayBuffer(o.length),i=new Uint8Array(a);for(let e=0;e<o.length;e++)i[e]=o.charCodeAt(e);return a}function n(){return void 0!==window?.PublicKeyCredential&&"function"==typeof window.PublicKeyCredential}function o(e){const{id:t}=e;return{...e,id:r(t),transports:e.transports}}function a(e){return"localhost"===e||/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(e)}class i extends Error{constructor({message:e,code:t,cause:r,name:n}){super(e,{cause:r}),this.name=n??r.name,this.code=t}}const s=new class{createNewAbortSignal(){if(this.controller){const e=new Error("Cancelling existing WebAuthn API call for new one");e.name="AbortError",this.controller.abort(e)}const e=new AbortController;return this.controller=e,e.signal}cancelCeremony(){if(this.controller){const e=new Error("Manually cancelling existing WebAuthn API call");e.name="AbortError",this.controller.abort(e),this.controller=void 0}}},c=["cross-platform","platform"];function l(e){if(e&&!(c.indexOf(e)<0))return e}function u(e,t){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${e}. You should report this error to them.\n`,t)}function d(){const e=window.PublicKeyCredential;return void 0===e.isConditionalMediationAvailable?new Promise((e=>e(!1))):e.isConditionalMediationAvailable()}e.WebAuthnAbortService=s,e.WebAuthnError=i,e.base64URLStringToBuffer=r,e.browserSupportsWebAuthn=n,e.browserSupportsWebAuthnAutofill=d,e.bufferToBase64URLString=t,e.platformAuthenticatorIsAvailable=function(){return n()?PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable():new Promise((e=>e(!1)))},e.startAuthentication=async function(e,c=!1){if(!n())throw new Error("WebAuthn is not supported in this browser");let u;0!==e.allowCredentials?.length&&(u=e.allowCredentials?.map(o));const h={...e,challenge:r(e.challenge),allowCredentials:u},f={};if(c){if(!await d())throw Error("Browser does not support WebAuthn autofill");if(document.querySelectorAll("input[autocomplete$='webauthn']").length<1)throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');f.mediation="conditional",h.allowCredentials=[]}let p;f.publicKey=h,f.signal=s.createNewAbortSignal();try{p=await navigator.credentials.get(f)}catch(e){throw function({error:e,options:t}){const{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if("AbortError"===e.name){if(t.signal instanceof AbortSignal)return new i({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else{if("NotAllowedError"===e.name)return new i({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if("SecurityError"===e.name){const t=window.location.hostname;if(!a(t))return new i({message:`${window.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e});if(r.rpId!==t)return new i({message:`The RP ID "${r.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else if("UnknownError"===e.name)return new i({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}({error:e,options:f})}if(!p)throw new Error("Authentication was not completed");const{id:w,rawId:R,response:E,type:g}=p;let A;var b;return E.userHandle&&(b=E.userHandle,A=new TextDecoder("utf-8").decode(b)),{id:w,rawId:t(R),response:{authenticatorData:t(E.authenticatorData),clientDataJSON:t(E.clientDataJSON),signature:t(E.signature),userHandle:A},type:g,clientExtensionResults:p.getClientExtensionResults(),authenticatorAttachment:l(p.authenticatorAttachment)}},e.startRegistration=async function(e){if(!n())throw new Error("WebAuthn is not supported in this browser");var c;const d={publicKey:{...e,challenge:r(e.challenge),user:{...e.user,id:(c=e.user.id,(new TextEncoder).encode(c))},excludeCredentials:e.excludeCredentials?.map(o)}};let h;d.signal=s.createNewAbortSignal();try{h=await navigator.credentials.create(d)}catch(e){throw function({error:e,options:t}){const{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if("AbortError"===e.name){if(t.signal instanceof AbortSignal)return new i({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else if("ConstraintError"===e.name){if(!0===r.authenticatorSelection?.requireResidentKey)return new i({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:e});if("required"===r.authenticatorSelection?.userVerification)return new i({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:e})}else{if("InvalidStateError"===e.name)return new i({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:e});if("NotAllowedError"===e.name)return new i({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if("NotSupportedError"===e.name)return 0===r.pubKeyCredParams.filter((e=>"public-key"===e.type)).length?new i({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:e}):new i({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:e});if("SecurityError"===e.name){const t=window.location.hostname;if(!a(t))return new i({message:`${window.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e});if(r.rp.id!==t)return new i({message:`The RP ID "${r.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else if("TypeError"===e.name){if(r.user.id.byteLength<1||r.user.id.byteLength>64)return new i({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:e})}else if("UnknownError"===e.name)return new i({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}({error:e,options:d})}if(!h)throw new Error("Registration was not completed");const{id:f,rawId:p,response:w,type:R}=h;let E,g,A,b;if("function"==typeof w.getTransports&&(E=w.getTransports()),"function"==typeof w.getPublicKeyAlgorithm)try{g=w.getPublicKeyAlgorithm()}catch(e){u("getPublicKeyAlgorithm()",e)}if("function"==typeof w.getPublicKey)try{const e=w.getPublicKey();null!==e&&(A=t(e))}catch(e){u("getPublicKey()",e)}if("function"==typeof w.getAuthenticatorData)try{b=t(w.getAuthenticatorData())}catch(e){u("getAuthenticatorData()",e)}return{id:f,rawId:t(p),response:{attestationObject:t(w.attestationObject),clientDataJSON:t(w.clientDataJSON),transports:E,publicKeyAlgorithm:g,publicKey:A,authenticatorData:b},type:R,clientExtensionResults:h.getClientExtensionResults(),authenticatorAttachment:l(h.authenticatorAttachment)}},Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function base64URLStringToBuffer(base64URLString: string): ArrayBuffer;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function browserSupportsWebAuthn(): boolean;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function browserSupportsWebAuthnAutofill(): Promise<boolean>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function bufferToBase64URLString(buffer: ArrayBuffer): string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function bufferToUTF8String(value: ArrayBuffer): string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function isValidDomain(hostname: string): boolean;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function platformAuthenticatorIsAvailable(): Promise<boolean>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function utf8StringToBuffer(value: string): ArrayBuffer;
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { AuthenticationResponseJSON, PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/types';
|
|
2
|
-
export declare function startAuthentication(requestOptionsJSON: PublicKeyCredentialRequestOptionsJSON, useBrowserAutofill?: boolean): Promise<AuthenticationResponseJSON>;
|
package/jest-environment.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { TestEnvironment } from 'jest-environment-jsdom';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Set up a custom JSDOM-based test environment for Jest so we can add things JSDOM doesn't support
|
|
5
|
-
*/
|
|
6
|
-
class CustomTestEnvironment extends TestEnvironment {
|
|
7
|
-
async setup() {
|
|
8
|
-
await super.setup();
|
|
9
|
-
/**
|
|
10
|
-
* JSDOM doesn't implement TextEncoder so we need to fake it with Node's
|
|
11
|
-
*
|
|
12
|
-
* Solved thanks to https://stackoverflow.com/a/57713960/2133271
|
|
13
|
-
*/
|
|
14
|
-
if (typeof this.global.TextEncoder === 'undefined') {
|
|
15
|
-
const { TextEncoder } = await import('util');
|
|
16
|
-
this.global.TextEncoder = TextEncoder;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Add support for TextDecoder to JSDOM
|
|
21
|
-
*/
|
|
22
|
-
if (typeof this.global.TextDecoder === 'undefined') {
|
|
23
|
-
const { TextDecoder } = await import('util');
|
|
24
|
-
this.global.TextDecoder = TextDecoder;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default CustomTestEnvironment;
|