diff --git a/public/build/portal/manifest.json b/public/build/portal/manifest.json index b6ceef19..14c179d2 100644 --- a/public/build/portal/manifest.json +++ b/public/build/portal/manifest.json @@ -25,6 +25,12 @@ "resources/js/error-reporting-sdk.js" ] }, + "resources/js/passkeys.js": { + "file": "passkeys-DaAq6jVJ.js", + "name": "passkeys", + "src": "resources/js/passkeys.js", + "isEntry": true + }, "resources/js/portal-form-hooks.js": { "file": "portal-form-hooks-DryiGN-B.js", "name": "portal-form-hooks", diff --git a/public/build/portal/passkeys-DaAq6jVJ.js b/public/build/portal/passkeys-DaAq6jVJ.js new file mode 100644 index 00000000..22f117b9 --- /dev/null +++ b/public/build/portal/passkeys-DaAq6jVJ.js @@ -0,0 +1,2 @@ +function d(e){const t=new Uint8Array(e);let n="";for(const o of t)n+=String.fromCharCode(o);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function E(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),n=(4-t.length%4)%4,r=t.padEnd(t.length+n,"="),o=atob(r),s=new ArrayBuffer(o.length),a=new Uint8Array(s);for(let c=0;ce};function U(e){const{id:t}=e;return{...e,id:E(t),transports:e.transports}}function x(e){return e==="localhost"||/^((xn--[a-z0-9-]+|[a-z0-9]+(-[a-z0-9]+)*)\.)+([a-z]{2,}|xn--[a-z0-9-]+)$/i.test(e)}class i extends Error{constructor({message:t,code:n,cause:r,name:o}){super(t,{cause:r}),Object.defineProperty(this,"code",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.name=o??r.name,this.code=n}}function j({error:e,options:t}){var r,o,s;const{publicKey:n}=t;if(!n)throw Error("options was missing required publicKey property");if(e.name==="AbortError"){if(t.signal instanceof AbortSignal)return new i({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else if(e.name==="ConstraintError"){if(((r=n.authenticatorSelection)==null?void 0:r.requireResidentKey)===!0)return new i({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:e});if(t.mediation==="conditional"&&((o=n.authenticatorSelection)==null?void 0:o.userVerification)==="required")return new i({message:"User verification was required during automatic registration but it could not be performed",code:"ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",cause:e});if(((s=n.authenticatorSelection)==null?void 0:s.userVerification)==="required")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(e.name==="InvalidStateError")return new i({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:e});if(e.name==="NotAllowedError")return new i({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if(e.name==="NotSupportedError")return n.pubKeyCredParams.filter(c=>c.type==="public-key").length===0?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(e.name==="SecurityError"){const a=globalThis.location.hostname;if(x(a)){if(n.rp.id!==a)return new i({message:`The RP ID "${n.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else return new i({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e})}else if(e.name==="TypeError"){if(n.user.id.byteLength<1||n.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(e.name==="UnknownError")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}class G{constructor(){Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0})}createNewAbortSignal(){if(this.controller){const n=new Error("Cancelling existing WebAuthn API call for new one");n.name="AbortError",this.controller.abort(n)}const t=new AbortController;return this.controller=t,t.signal}cancelCeremony(){if(this.controller){const t=new Error("Manually cancelling existing WebAuthn API call");t.name="AbortError",this.controller.abort(t),this.controller=void 0}}}const D=new G,q=["cross-platform","platform"];function L(e){if(e&&!(q.indexOf(e)<0))return e}async function F(e){var g;!e.optionsJSON&&e.challenge&&(console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:t,useAutoRegister:n=!1}=e;if(!S())throw new Error("WebAuthn is not supported in this browser");const r={...t,challenge:E(t.challenge),user:{...t.user,id:E(t.user.id)},excludeCredentials:(g=t.excludeCredentials)==null?void 0:g.map(U)},o={};n&&(o.mediation="conditional"),o.publicKey=r,o.signal=D.createNewAbortSignal();let s;try{s=await navigator.credentials.create(o)}catch(l){throw j({error:l,options:o})}if(!s)throw new Error("Registration was not completed");const{id:a,rawId:c,response:u,type:O}=s;let h;typeof u.getTransports=="function"&&(h=u.getTransports());let y;if(typeof u.getPublicKeyAlgorithm=="function")try{y=u.getPublicKeyAlgorithm()}catch(l){T("getPublicKeyAlgorithm()",l)}let m;if(typeof u.getPublicKey=="function")try{const l=u.getPublicKey();l!==null&&(m=d(l))}catch(l){T("getPublicKey()",l)}let w;if(typeof u.getAuthenticatorData=="function")try{w=d(u.getAuthenticatorData())}catch(l){T("getAuthenticatorData()",l)}return{id:a,rawId:d(c),response:{attestationObject:d(u.attestationObject),clientDataJSON:d(u.clientDataJSON),transports:h,publicKeyAlgorithm:y,publicKey:m,authenticatorData:w},type:O,clientExtensionResults:s.getClientExtensionResults(),authenticatorAttachment:L(s.authenticatorAttachment)}}function T(e,t){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${e}. You should report this error to them. +`,t)}function B(){if(!S())return I.stubThis(new Promise(t=>t(!1)));const e=globalThis.PublicKeyCredential;return(e==null?void 0:e.isConditionalMediationAvailable)===void 0?I.stubThis(new Promise(t=>t(!1))):I.stubThis(e.isConditionalMediationAvailable())}const I={stubThis:e=>e};function $({error:e,options:t}){const{publicKey:n}=t;if(!n)throw Error("options was missing required publicKey property");if(e.name==="AbortError"){if(t.signal instanceof AbortSignal)return new i({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else{if(e.name==="NotAllowedError")return new i({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if(e.name==="SecurityError"){const r=globalThis.location.hostname;if(x(r)){if(n.rpId!==r)return new i({message:`The RP ID "${n.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else return new i({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e})}else if(e.name==="UnknownError")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}async function k(e){var w,g;!e.optionsJSON&&e.challenge&&(console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:t,useBrowserAutofill:n=!1,verifyBrowserAutofillInput:r=!0}=e;if(!S())throw new Error("WebAuthn is not supported in this browser");let o;((w=t.allowCredentials)==null?void 0:w.length)!==0&&(o=(g=t.allowCredentials)==null?void 0:g.map(U));const s={...t,challenge:E(t.challenge),allowCredentials:o},a={};if(n){if(!await B())throw Error("Browser does not support WebAuthn autofill");if(document.querySelectorAll("input[autocomplete$='webauthn']").length<1&&r)throw Error('No with "webauthn" as the only or last value in its `autocomplete` attribute was detected');a.mediation="conditional",s.allowCredentials=[]}a.publicKey=s,a.signal=D.createNewAbortSignal();let c;try{c=await navigator.credentials.get(a)}catch(l){throw $({error:l,options:a})}if(!c)throw new Error("Authentication was not completed");const{id:u,rawId:O,response:h,type:y}=c;let m;return h.userHandle&&(m=d(h.userHandle)),{id:u,rawId:d(O),response:{authenticatorData:d(h.authenticatorData),clientDataJSON:d(h.clientDataJSON),signature:d(h.signature),userHandle:m},type:y,clientExtensionResults:c.getClientExtensionResults(),authenticatorAttachment:L(c.authenticatorAttachment)}}class p extends Error{constructor(t){super(t),this.name="PasskeyError"}}class A extends p{constructor(){super("Passkeys are not supported in this browser."),this.name="NotSupportedError"}}class M extends p{constructor(){super("The passkey operation was cancelled."),this.name="UserCancelledError"}}class H extends p{constructor(){super("This device is already registered as a passkey."),this.name="PasskeyExistsError"}}class J extends p{constructor(t){const n=t??"this domain";super(`Passkeys can't be used on ${n}. For local development, use localhost.`),this.name="InvalidDomainError"}}const _=e=>{if(e instanceof p)return e;if(!(e instanceof Error))return new p("An unknown error occurred.");if(Y(e))return new J(X());switch(e.name){case"NotAllowedError":return new M;case"InvalidStateError":return new H;case"NotSupportedError":return new A;default:return new p(e.message)}},Y=e=>z(e)==="ERROR_INVALID_DOMAIN",z=e=>"code"in e&&typeof e.code=="string"?e.code:void 0,X=()=>{var e;return typeof((e=globalThis.location)==null?void 0:e.hostname)=="string"&&globalThis.location.hostname.length>0?globalThis.location.hostname:void 0};let f={};const Q=e=>{var t,n;f={...f,...e,fetch:{...f.fetch,...e.fetch,headers:{...(t=f.fetch)==null?void 0:t.headers,...(n=e.fetch)==null?void 0:n.headers}}}},Z=()=>typeof document>"u"?null:ee()||te(),ee=()=>{const e=document.querySelector('meta[name="csrf-token"]');if(!e)return null;const t=e.getAttribute("content");return t?{header:"X-CSRF-TOKEN",value:t}:null},te=()=>{const e="XSRF-TOKEN=",t=document.cookie.split("; ").find(r=>r.startsWith(e));if(!t)return null;const n=t.slice(e.length);return n?{header:"X-XSRF-TOKEN",value:decodeURIComponent(n)}:null},N=async e=>{var n,r;const t=await fetch(e,{method:"GET",headers:{Accept:"application/json",...(n=f.fetch)==null?void 0:n.headers},credentials:((r=f.fetch)==null?void 0:r.credentials)??"same-origin"});return t.ok||await V(t),t.json()},P=async(e,t)=>{var s,a;const n=Z(),r={"Content-Type":"application/json",Accept:"application/json",...(s=f.fetch)==null?void 0:s.headers};n&&(r[n.header]=n.value);const o=await fetch(e,{method:"POST",headers:r,credentials:((a=f.fetch)==null?void 0:a.credentials)??"same-origin",body:JSON.stringify(t)});return o.ok||await V(o),o.json()},V=async e=>{let t=`Request failed with status ${e.status}`;try{const n=await e.json();n&&typeof n=="object"&&"message"in n&&typeof n.message=="string"&&(t=n.message)}catch{}throw new Error(t)},K=e=>(typeof e=="function"?e():e)??!1,b={registerOptions:"/user/passkeys/options",registerStore:"/user/passkeys",verifyOptions:"/passkeys/login/options",verifySubmit:"/passkeys/login"},R={configure(e){Q(e)},isSupported(){return S()},async isAutofillSupported(){return B()},async register(e){if(!this.isSupported())throw new A;this.cancel();try{const t=v(e,{options:b.registerOptions,submit:b.registerStore}),{options:n}=await N(t.optionsRoute),r=await F({optionsJSON:n}),o={name:e.name,credential:r};return await P(t.submitRoute,o)}catch(t){throw _(t)}},async verify(e={}){if(!this.isSupported())throw new A;this.cancel();try{const t=v(e,{options:b.verifyOptions,submit:b.verifySubmit}),{options:n}=await N(t.optionsRoute),r={credential:await k({optionsJSON:n}),remember:K(e.remember)};return await P(t.submitRoute,r)}catch(t){throw _(t)}},async autofill(e={}){if(!(!this.isSupported()||!await this.isAutofillSupported()))try{const t=v(e,{options:b.verifyOptions,submit:b.verifySubmit}),{options:n}=await N(t.optionsRoute),r={credential:await k({optionsJSON:n,useBrowserAutofill:!0}),remember:K(e.remember)};return await P(t.submitRoute,r)}catch(t){if(t instanceof Error&&["AbortError","NotAllowedError"].includes(t.name))return;throw _(t)}},cancel(){D.cancelCeremony()}},v=(e,t)=>{var n,r;return{optionsRoute:((n=e.routes)==null?void 0:n.options)??t.options,submitRoute:((r=e.routes)==null?void 0:r.submit)??t.submit}},ne={options:"/passkeys/confirm/options",submit:"/passkeys/confirm"};function re(e){return e instanceof M?"Der Vorgang wurde abgebrochen.":e instanceof A?"Dieser Browser unterstützt keine Passkeys.":e instanceof H?"Für dieses Gerät ist bereits ein Passkey hinterlegt.":e instanceof J?"Passkeys funktionieren nur auf der Anmeldeseite von pressekonto.":"Der Passkey konnte nicht geprüft werden. Bitte versuchen Sie es erneut."}async function C(e){try{return{ok:!0,error:null,result:await e()}}catch(t){return{ok:!1,error:re(t),result:null}}}window.PkPasskeys={isSupported:()=>R.isSupported(),login:(e=!1)=>C(()=>R.verify({remember:e})),confirm:()=>C(()=>R.verify({routes:ne})),register:e=>C(()=>R.register({name:e}))};