@crossauth/sveltekit 1.0.1 → 1.1.0
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/README.md +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/sveltekitapikey.d.ts +2 -1
- package/dist/sveltekitoauthclient.d.ts +2 -1
- package/dist/sveltekitresserver.d.ts +2 -1
- package/dist/sveltekitserver.d.ts +2 -1
- package/dist/sveltekitsession.d.ts +3 -2
- package/dist/tests/sveltemocks.d.ts +21 -6
- package/package.json +20 -14
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("minimatch"),u=require("@crossauth/backend"),r=require("@crossauth/common"),m=require("@sveltejs/kit");require("cookie");const P=require("jwt-decode"),$=require("qrcode");class z{constructor(s){this.values=[],this.keys=[],this.i=0;for(let i in s)this.keys.push(i),this.values.push(s[i])}next(){if(this.i==this.values.length)return{done:!0,value:["",""]};const s=[this.keys[this.i],this.values[this.i]];return this.i++,{done:!1,value:s[0]}}[Symbol.iterator](){return this}}class S{constructor(s=!0){this.clone=s}async loadData(s){var o,e,t,n;if(!((o=s.request)!=null&&o.body))return;const i=s.request.headers.get("content-type");i=="application/json"?this.jsonData=this.clone?await((t=(e=s.request)==null?void 0:e.clone())==null?void 0:t.json()):await((n=s.request)==null?void 0:n.json()):(i=="application/x-www-form-urlencoded"||i!=null&&i.startsWith("multipart/form-data"))&&(this.formData=this.clone?await s.request.clone().formData():await s.request.formData())}get(s){if(this.jsonData)return this.jsonData[s];if(this.formData){const i=this.formData.get(s);if(i&&typeof i=="string")return i}}getAsString(s){return this.get(s)}getAsBoolean(s){const i=this.get(s);if(i==null)return;const o=i.toLowerCase();return o=="t"||o=="true"||o=="1"||o=="y"||o=="yes"||o=="on"}getAsNumber(s){const i=this.get(s);if(i!=null)try{return Number(i)}catch{throw new r.CrossauthError(r.ErrorCode.FormEntry,"Value for "+s+" is not a number")}}has(s){return(this.jsonData&&s in this.jsonData||this.formData&&this.formData.has(s))??!1}keys(){return this.jsonData?new z(this.jsonData):this.formData?this.formData.keys():new z({})}toObject(){var s;if(this.jsonData)return this.jsonData;if(this.formData){let i={};for(let o of this.formData.entries())i[o[0]]=((s=o[1])==null?void 0:s.toString())??"";return i}return{}}}class x{constructor(s,i,o={}){this.userStorage=s,this.apiKeyManager=new u.ApiKeyManager(i,o),this.hook=async({event:e})=>{r.CrossauthLogger.logger.debug("APIKey hook");const t=e.request.headers.get("authorization");if(t)try{r.CrossauthLogger.logger.debug(r.j({msg:"Received authorization header"}));const n=await this.apiKeyManager.validateToken(t);r.CrossauthLogger.logger.debug(r.j({msg:"Valid API key",hahedApiKey:u.ApiKeyManager.hashSignedApiKeyValue(n.value)}));const a=u.KeyStorage.decodeData(n.data);if(e.locals.apiKey={...n,...a},"scope"in a&&Array.isArray(a.scope)){let c=[];for(let l of a.scope)typeof l=="string"&&c.push(l);e.locals.scope=c}if(n.userid)try{const{user:c}=await this.userStorage.getUserById(n.userid);e.locals.user=c,e.locals.authType="apiKey",r.CrossauthLogger.logger.debug(r.j({msg:"API key is for user",userid:c.id,user:c.username,hahedApiKey:u.ApiKeyManager.hashSignedApiKeyValue(n.value)}))}catch(c){r.CrossauthLogger.logger.error(r.j({msg:"API key has invalid user",userid:n.userid,hashedApiKey:u.ApiKeyManager.hashSignedApiKeyValue(n.value)})),r.CrossauthLogger.logger.debug(r.j({err:c}))}}catch(n){r.CrossauthLogger.logger.error(r.j({msg:"Invalid authorization header received",header:t})),r.CrossauthLogger.logger.debug(r.j({err:n}))}}}}const K="upstreamoauth";class B{constructor(s,i,o,e,t={}){var n;this.loginUrl="/login",this.refreshTokenType="json",this.refreshTokenCookieName="CROSSAUTH_REFRESH_TOKEN",this.refreshTokenCookieDomain=void 0,this.refreshTokenCookieHttpOnly=!1,this.refreshTokenCookiePath="/",this.refreshTokenCookieSecure=!0,this.refreshTokenCookieSameSite="strict",this.authorizeEndpointUrl="/oauth/authorize",this.tokenEndpointUrl="/oauth/token",this.jwksEndpointUrl="/oauth/jwks",this.oidcConfigurationEndpoint={get:async a=>m.json(this.authServer.oidcConfiguration({authorizeEndpoint:this.authorizeEndpointUrl,tokenEndpoint:this.tokenEndpointUrl,jwksUri:this.jwksEndpointUrl,additionalClaims:[]}))},this.jwksGetEndpoint={get:async a=>{try{return m.json(this.authServer.jwks())}catch(c){const l=r.CrossauthError.asCrossauthError(c);return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),m.json({error:l.oauthErrorCode,error_description:l.message})}}},this.getCsrfTokenEndpoint={get:async a=>{var l;if(!this.csrfTokens)return m.json({ok:!1,error:"invalid_request",error_description:"No CSRF token"});let c="";try{const{csrfCookie:h,csrfFormOrHeaderValue:d}=await this.createCsrfToken();return c=h.value,a.cookies.set(h.name,h.value,u.toCookieSerializeOptions(h.options)),m.json({ok:!0,csrfToken:d})}catch(h){const d=r.CrossauthError.asCrossauthError(h);return r.CrossauthLogger.logger.error(r.j({msg:"getcsrftoken failure",user:(l=a.locals.user)==null?void 0:l.username,hashedCsrfCookie:u.Crypto.hash(c.split(".")[0]),error:d.code,errorCodeName:d.codeName})),r.CrossauthLogger.logger.debug(r.j({err:h})),r.CrossauthLogger.logger.error({cerr:h}),m.json({ok:!1,error:d.oauthErrorCode,error_description:d.message})}}},this.authorizeEndpoint={load:async a=>{var g,E;if(!(this.authServer.validFlows.includes(r.OAuthFlows.AuthorizationCode)||this.authServer.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)||this.authServer.validFlows.includes(r.OAuthFlows.OidcAuthorizationCode)))throw this.error(401,"authorize cannot be called because the authorization code flows are not supported");if(this.authServer.upstreamClient&&this.authServer.upstreamClientOptions){const w=u.Crypto.randomValue(32);let k=this.getAuthorizeQuery(a);if(!k.query)return k.error;let y=k.query;if(y.response_type=="code"){let _;try{_=await this.clientStorage.getClientById(y.client_id)}catch(F){return r.CrossauthLogger.logger.debug(r.j({err:F})),{ok:!1,error:"unauthorized_client",error_description:"Client is not authorized"}}let v;y.scope&&(v=decodeURIComponent(y.scope).split(" ")),v=v==null?void 0:v.filter(F=>F.length>0);const A=await this.authServer.upstreamClient.startAuthorizationCodeFlow(w,y.scope,y.code_challenge,y.code_challenge!=null);if(A.error)return{ok:!1,error:A.error,error_description:A.error_description};{const F=await this.authServer.getAuthorizationCode(_,y.redirect_uri,v,w,y.code_challenge,y.code_challenge_method);if(!F.code)return{ok:!1,error:"server_error",error_description:"Couldn't create authorization code"};const Y={scope:y.scope,state:w,code:F.code,orig_client_id:y.client_id,orig_redirect_uri:y.redirect_uri,orig_state:y.state};if(!this.authServer.upstreamClientOptions.options.redirect_uri)return{ok:!1,error:"server_error",error_description:"redirect uri not given for upstream client"};const X=this.authServer.upstreamClientOptions.sessionDataName??K;await this.storeSessionData(a,Y,X);let D=A.url;throw r.CrossauthLogger.logger.debug(r.j({msg:"upstream url "+D})),this.redirect(302,D)}}else return{ok:!1,error:"invalid_request",error_description:"authorize can only be called with response_type code"}}if(!a.locals.user)return this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(a.request.url));let c=this.getAuthorizeQuery(a);if(!c.query)return c.error;let l=c.query;r.CrossauthLogger.logger.debug(r.j({msg:"validating authorize parameters"}));let{error_description:h}=this.authServer.validateAuthorizeParameters(l),d;if(h?(d=new r.CrossauthError(r.ErrorCode.BadRequest,h),r.CrossauthLogger.logger.error(r.j({msg:"authorize parameter invalid",cerr:d,user:(g=a.locals.user)==null?void 0:g.username}))):r.CrossauthLogger.logger.error(r.j({msg:"authorize parameter valid",user:(E=a.locals.user)==null?void 0:E.username})),d)return{ok:!1,error:d.oauthErrorCode,error_description:d.message};let f=!1;if(r.CrossauthLogger.logger.debug(r.j({msg:"Checking scopes have been authorized",scope:l.scope})),l.scope?f=await this.authServer.hasAllScopes(l.client_id,a.locals.user,l.scope.split(" ")):f=await this.authServer.hasAllScopes(l.client_id,a.locals.user,[null]),f){r.CrossauthLogger.logger.debug(r.j({msg:"All scopes authorized",scope:l.scope}));const w=await this.authorize(a,!0,{responseType:l.response_type,client_id:l.client_id,redirect_uri:l.redirect_uri,scope:l.scope,state:l.state,codeChallenge:l.code_challenge,codeChallengeMethod:l.code_challenge_method});return{ok:!1,error:w.error??"server_error",error_description:w.error_description??"An unexpected error occurred"}}else{r.CrossauthLogger.logger.debug(r.j({msg:"Not all scopes authorized",scope:l.scope}));try{const w=await this.clientStorage.getClientById(l.client_id);return{ok:!0,authorizationNeeded:{user:a.locals.user,response_type:l.response_type,client_id:l.client_id,client_name:w.client_name,redirect_uri:l.redirect_uri,scope:l.scope,scopes:l.scope?l.scope.split(" "):void 0,state:l.state,code_challenge:l.code_challenge,code_challenge_method:l.code_challenge_method,csrfToken:a.locals.csrfToken},...this.baseEndpoint}}catch(w){const k=w;return r.CrossauthLogger.logger.debug(r.j({err:k})),{ok:!1,error:"unauthorized_client",error_description:"Not a valid client"}}}},actions:{default:async a=>{var h;let c;try{var l=new S;await l.loadData(a),c=l.toObject();const d=l.getAsBoolean("authorized"),f=c.response_type,g=c.client_id,E=c.redirect_uri,w=c.scope,k=c.state,y=c.code_challenge,_=c.code_challenge_method;let v;if(d==null&&(v="authorized"),f?g?E?k||(v="state"):v="redirect_uri":v="client_id":v="response_type",v)return{ok:!1,error:"invalid_request",error_description:"Invalid form: does not contain "+v+" parameter"};if(!a.locals.user)return this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(a.request.url));if((h=this.svelteKitServer.sessionServer)!=null&&h.enableCsrfProtection&&!a.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const A=await this.authorize(a,d??!1,{responseType:f,client_id:g,redirect_uri:E,scope:w,state:k,codeChallenge:y,codeChallengeMethod:_});return{ok:!1,error:A.error??"server_error",error_description:A.error_description??"An unexpected error occurred"}}catch(d){if(C.isSvelteKitError(d)||C.isSvelteKitRedirect(d))throw d;let f=r.CrossauthError.asCrossauthError(d,"Couldn't process authorization code");return{error:f.oauthErrorCode,error_description:f.message,ok:!1,formData:c}}}}},this.tokenEndpoint={post:async a=>{let c;try{if(!(this.authServer.validFlows.includes(r.OAuthFlows.AuthorizationCode)||this.authServer.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)||this.authServer.validFlows.includes(r.OAuthFlows.OidcAuthorizationCode)||this.authServer.validFlows.includes(r.OAuthFlows.ClientCredentials)||this.authServer.validFlows.includes(r.OAuthFlows.RefreshToken)||this.authServer.validFlows.includes(r.OAuthFlows.Password)||this.authServer.validFlows.includes(r.OAuthFlows.PasswordMfa||this.authServer.validFlows.includes(r.OAuthFlows.DeviceCode))))return m.json({ok:!1,error:"invalid_request",error_description:"Token endpoint cannot be called as the supported OAuth flow types don't require it"},{status:500});var l=new S;await l.loadData(a),c=l.toObject();const{client_id:h,client_secret:d}=this.getClientIdAndSecret(c,a);if(c.grant_type=="authorization_code"&&this.authServer.upstreamClient&&this.authServer.upstreamClientOptions){const w=await this.authServer.getAuthorizationCodeData(c.code);return w==null?m.json({error:"access_denied",error_description:"Invalid or expired authorization code"}):w.access_token?(await this.authServer.deleteAuthorizationCodeData(c.code),m.json({access_token:w.access_token,id_token:w.id_token,id_payload:w.id_payload,refresh_token:w.refresh_token,expires_in:w.expires_in})):m.json({error:"access_denied",error_description:"No access token was issued"},{status:401})}let f=c.refresh_token,g=a.cookies.get(this.refreshTokenCookieName);if((this.refreshTokenType=="cookie"&&g||this.refreshTokenType=="both"&&g&&f==null)&&this.csrfTokens){const w=a.cookies.get(this.csrfTokens.cookieName);let k=a.request.headers.get(this.csrfTokens.headerName.toLowerCase());if(Array.isArray(k)&&(k=k[0]),!w||!k)return m.json({ok:!1,error:"access_denied",error_description:"Invalid csrf token"},{status:401});try{this.csrfTokens.validateDoubleSubmitCsrfToken(w,k)}catch(y){return r.CrossauthLogger.logger.debug(r.j({err:y})),r.CrossauthLogger.logger.warn(r.j({cerr:y,msg:"Invalid csrf token",client_id:c.client_id})),m.json({ok:!1,error:"access_denied",error_description:"Invalid csrf token"},{status:401})}f=g}const E=await this.authServer.tokenEndpoint({grantType:c.grant_type,client_id:h,client_secret:d,scope:c.scope,codeVerifier:c.code_verifier,code:c.code,username:c.username,password:c.password,mfaToken:c.mfa_token,oobCode:c.oob_code,bindingCode:c.binding_code,otp:c.otp,refreshToken:f,deviceCode:c.device_code});if(E.refresh_token&&this.refreshTokenType!="json"&&this.setRefreshTokenCookie(a,E.refresh_token,E.expires_in),E.error=="authorization_pending")return m.json(E);if(E.error||!E.access_token){let w="server_error",k="Neither code nor error received when requestoing authorization";E.error&&(w=E.error),E.error_description&&(k=E.error_description);const y=r.CrossauthError.fromOAuthError(w,k);return r.CrossauthLogger.logger.error(r.j({cerr:y})),m.json(E,{status:y.httpStatus})}return m.json(E)}catch(h){const d=r.CrossauthError.asCrossauthError(h);return r.CrossauthLogger.logger.debug({err:h}),r.CrossauthLogger.logger.error({cerr:h}),m.json({error:d.oauthErrorCode,error_description:d.message},{status:d.httpStatus})}}},this.upstreamRedirectUriEndpoint={get:async a=>{var l;let c={};try{if(!this.authServer.upstreamClientOptions)return r.CrossauthLogger.logger.error(r.j({msg:"Cannot call upstreamRedirectUriEndpoint if upstreamClient not defined"})),m.json({ok:!1,error:"server_error",error_description:"Cannot call upstreamRedirectUriEndpoint if upstreamClient not defined"});if(r.CrossauthLogger.logger.debug(r.j({msg:"upstreamRedirectUriEndpoint"})),!this.authServer.upstreamClient||!this.authServer.upstreamClientOptions.tokenMergeFn)return r.CrossauthLogger.logger.error(r.j({msg:"upstreamRedirectUri endpoint called but no upstreamClient or merge function set"})),this.redirectError(c.orig_redirect_uri,"server_error","upstreamRedirectUri endpoint called but no upstreamClient or merge function set");const h=a.url.searchParams.get("code")??"",d=a.url.searchParams.get("state")??void 0,f=a.url.searchParams.get("error")??void 0,g=a.url.searchParams.get("error")??void 0,E=this.authServer.upstreamClientOptions.sessionDataName??K;if(c=await((l=this.svelteKitServer.sessionAdapter)==null?void 0:l.getSessionData(a,E))??{},(c==null?void 0:c.state)!=d)throw r.CrossauthLogger.logger.error(r.j({msg:"State does not match"})),new r.CrossauthError(r.ErrorCode.Unauthorized,"State does not match");const w=await this.authServer.upstreamClient.redirectEndpoint(h,c==null?void 0:c.scope,c==null?void 0:c.codeVerifier,f,g);if(w.error)return r.CrossauthLogger.logger.error(r.j({msg:w.error_description})),this.redirectError(c.orig_redirect_uri,w.error,w.error_description??"unknown error");let k=w.access_token;if(w.access_token&&this.authServer.upstreamClientOptions.accessTokenIsJwt){const _=await this.authServer.upstreamClient.getAccessPayload(w.access_token,!1);if(_.error)return m.json(_);if(_.payload)k=_.payload;else return r.CrossauthLogger.logger.error(r.j({msg:"No error or access payload received when querying access token"})),this.redirectError(c.orig_redirect_uri,"server_error","No error or access payload received when querying access token")}const y=await this.authServer.upstreamClientOptions.tokenMergeFn(k??"",w.id_payload,this.authServer.userStorage);if(y.authorized){const _=await this.authServer.createTokensFromPayload(c.orig_client_id,y.access_payload,y.id_payload);c={...c,access_token:_.access_token,id_token:_.id_token,id_payload:_.id_payload,expires_in:_.expires_in,refresh_token:w.refresh_token};let v=await this.authServer.getAuthorizationCodeData(c.code);throw v={...v,access_token:_.access_token,id_token:_.id_token,id_payload:_.id_token,refresh_token:w.refresh_token,expires_in:_.expires_in},await this.authServer.setAuthorizationCodeData(c.code,v),this.redirect(302,this.authServer.redirect_uri(c.orig_redirect_uri,c.code,c.orig_state))}else return r.CrossauthLogger.logger.error(r.j({msg:y.error_description??"Error merging tokens"})),this.redirectError(c.orig_redirect_uri,y.error??"server_error",y.error_description??"Error merging tokens")}catch(h){if(C.isSvelteKitRedirect(h)||C.isSvelteKitError(h))throw h;const d=r.CrossauthError.asCrossauthError(h);return r.CrossauthLogger.logger.debug({err:h}),r.CrossauthLogger.logger.error({cerr:h}),this.redirectError(c.orig_redirect_uri,d.oauthErrorCode,d.message)}}},this.mfaAuthenticatorsEndpoint={get:async a=>{try{var c=new S;return await c.loadData(a),m.json(await this.mfaAuthenticators(a))}catch(l){const h=r.CrossauthError.asCrossauthError(l);return r.CrossauthLogger.logger.debug({err:l}),r.CrossauthLogger.logger.error({cerr:l}),m.json({error:h.oauthErrorCode,error_description:h.message})}},post:async a=>{try{var c=new S;await c.loadData(a);let l=await this.mfaAuthenticators(a),h=200;return!Array.isArray(l)&&l.error=="access_denied"?h=401:!Array.isArray(l)&&l.error&&(h=500),m.json(l,{status:h})}catch(l){const h=r.CrossauthError.asCrossauthError(l);return r.CrossauthLogger.logger.debug({err:l}),r.CrossauthLogger.logger.error({cerr:l}),m.json({error:h.oauthErrorCode,error_description:h.message},{status:h.httpStatus})}}},this.mfaChallengeEndpoint={post:async a=>{try{var c=new S;await c.loadData(a);const l=await this.mfaChallenge(a);let h=200;return l.error=="access_denied"?h=401:l.error&&(h=500),m.json(l,{status:h})}catch(l){const h=r.CrossauthError.asCrossauthError(l);return r.CrossauthLogger.logger.debug({err:l}),r.CrossauthLogger.logger.error({cerr:l}),m.json({error:h.oauthErrorCode,error_description:h.message},{status:500})}}},this.deviceAuthorizationEndpoint={post:async a=>{let c;try{if(!this.authServer.validFlows.includes(r.OAuthFlows.DeviceCode))return m.json({ok:!1,error:"invalid_request",error_description:"Device authorization endpoint cannot be called as the supported OAuth flow types don't require it"});var l=new S;await l.loadData(a),c=l.toObject();const{client_id:h,client_secret:d}=this.getClientIdAndSecret(c,a),f=await this.authServer.deviceAuthorizationEndpoint({client_id:h,client_secret:d,scope:c.scope});if(f.error){const g=r.CrossauthError.fromOAuthError(f.error,f.error_description);return r.CrossauthLogger.logger.error(r.j({cerr:g})),m.json(f,{status:500})}if(!f.device_code||!f.user_code||!f.verification_uri||!f.verification_uri_complete||!f.expires_in){let g="server_error",E="Device authorization result has missing data";const w=new r.CrossauthError(r.ErrorCode.UnknownError,E);return r.CrossauthLogger.logger.error(r.j({cerr:w})),m.json({error:g,error_description:E},{status:500})}return m.json(f)}catch(h){const d=r.CrossauthError.asCrossauthError(h);return r.CrossauthLogger.logger.debug({err:h}),r.CrossauthLogger.logger.error({cerr:h}),m.json({error:d.oauthErrorCode,error_description:d.message},{status:500})}}},this.deviceEndpoint={load:async a=>{if(!this.authServer.validFlows.includes(r.OAuthFlows.DeviceCode))throw this.error(401,"device cannot be called because the device code flow is not supported");if(!a.locals.user)return this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(a.request.url));let c=a.url.searchParams.get("user_code");return c?await this.applyUserCode(c,a,a.locals.user):{ok:!0,completed:!1,retryAllowed:!0,user:a.locals.user,csrfToken:a.locals.csrfToken}},actions:{userCode:async a=>{if(!a.locals.user)throw this.error(401,"Access Denied");try{var c=new S;await c.loadData(a);const l=c.get("user_code");return l?await this.applyUserCode(l,a,a.locals.user):{ok:!1,completed:!1,retryAllowed:!0,error:"access_denied",error_description:"No user code given"}}catch(l){if(C.isSvelteKitError(l)||C.isSvelteKitRedirect(l))throw l;let h=r.CrossauthError.asCrossauthError(l,"Couldn't validate user code");return{ok:!1,completed:!1,retryAllowed:!0,error:h.oauthErrorCode,error_description:h.message}}},authorize:async a=>{var h;let c;try{var l=new S;await l.loadData(a),c=l.toObject();const d=l.getAsBoolean("authorized"),f=c.scope,g=c.client_id,E=c.user_code;let w;if(d==null&&(w="authorized"),g==null&&(w="client_id"),E==null&&(w="user_code"),w)return{ok:!1,completed:!1,retryAllowed:!1,error:"invalid_request",error_description:"Invalid form: does not contain "+w+" parameter"};if(!a.locals.user)return this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(a.request.url));if((h=this.svelteKitServer.sessionServer)!=null&&h.enableCsrfProtection&&!a.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);return(await this.authServer.validateAndPersistScope(g,f,a.locals.user)).error?{ok:!1,completed:!1,retryAllowed:!1,error:"unauthorized_client",error_description:"You did not authorize access to your account"}:await this.applyUserCode(E,a,a.locals.user)}catch(d){if(C.isSvelteKitError(d)||C.isSvelteKitRedirect(d))throw d;let f=r.CrossauthError.asCrossauthError(d,"Couldn't process authorization code");return{error:f.oauthErrorCode,error_description:f.message,ok:!1,completed:!1,retryAllowed:!1}}}}},this.svelteKitServer=s,this.clientStorage=i,t.redirect&&(this.redirect=t.redirect),t.error&&(this.error=t.error),this.authServer=new u.OAuthAuthorizationServer(this.clientStorage,o,e,t),u.setParameter("loginUrl",u.ParamType.String,this,t,"LOGIN_URL"),u.setParameter("refreshTokenType",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_TYPE"),u.setParameter("refreshTokenCookieName",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_NAME"),u.setParameter("refreshTokenCookieDomain",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_DOMAIN"),u.setParameter("refreshTokenCookieHttpOnly",u.ParamType.Boolean,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_HTTPONLY"),u.setParameter("refreshTokenCookiePath",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_PATH"),u.setParameter("refreshTokenCookieSecure",u.ParamType.Boolean,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_SECURE"),u.setParameter("refreshTokenCookieSameSite",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_SAMESITE"),u.setParameter("authorizeEndpointUrl",u.ParamType.String,this,t,"OAUTH_AUTHORIZE_ENDPOINT"),u.setParameter("tokenEndpointUrl",u.ParamType.String,this,t,"OAUTH_TOKEN_ENDPOINT"),u.setParameter("jwksEndpointUrl",u.ParamType.String,this,t,"OAUTH_JWKS_ENDPOINT"),this.refreshTokenType!="json"&&(((n=this.svelteKitServer.sessionServer)==null?void 0:n.enableCsrfProtection)==!0?this.csrfTokens=this.svelteKitServer.sessionServer.sessionManager.csrfTokens:this.csrfTokens=new u.DoubleSubmitCsrfToken(t.doubleSubmitCookieOptions))}oidcConfiguration(){return this.authServer.oidcConfiguration({authorizeEndpoint:this.authorizeEndpointUrl,tokenEndpoint:this.tokenEndpointUrl,jwksUri:this.jwksEndpointUrl,additionalClaims:[]})}async authorize(s,i,{responseType:o,client_id:e,redirect_uri:t,scope:n,state:a,codeChallenge:c,codeChallengeMethod:l}){let h,d,f;if(i){const g=await this.authServer.authorizeGetEndpoint({responseType:o,client_id:e,redirect_uri:t,scope:n,state:a,codeChallenge:c,codeChallengeMethod:l,user:s.locals.user});if(f=g.code,h=g.error,d=g.error_description,h||!f){const E=r.CrossauthError.fromOAuthError(h??"server_error",d??"Neither code nor error received");return r.CrossauthLogger.logger.error(r.j({cerr:E})),{ok:!1,error:h,error_description:d}}throw this.redirect(302,this.authServer.redirect_uri(t,f,a))}else{const g=new r.CrossauthError(r.ErrorCode.Unauthorized,"You have not granted access");r.CrossauthLogger.logger.debug(r.j({err:g})),r.CrossauthLogger.logger.error(r.j({cerr:g})),r.CrossauthLogger.logger.error(r.j({msg:d,errorCode:g.code,errorCodeName:g.codeName}));try{throw u.OAuthClientManager.validateUri(t),this.redirect(302,t+"?error=access_denied&error_description="+encodeURIComponent("Access was not granted"))}catch(E){if(C.isSvelteKitError(E)||C.isSvelteKitRedirect(E))throw E;return r.CrossauthLogger.logger.error(r.j({msg:`Couldn't send error message ${g.codeName} to ${t}}`})),{ok:!1,error:"server_error",error_description:"Redirect Uri is not valid"}}}}async createCsrfToken(){if(!this.csrfTokens)throw new r.CrossauthError(r.ErrorCode.Configuration,"CSRF tokens not enabled");this.csrfTokens.makeCsrfCookie(this.csrfTokens.createCsrfToken());const s=this.csrfTokens.createCsrfToken(),i=this.csrfTokens.makeCsrfFormOrHeaderToken(s);return{csrfCookie:this.csrfTokens.makeCsrfCookie(s),csrfFormOrHeaderValue:i}}setRefreshTokenCookie(s,i,o){if(!this.refreshTokenCookieName)return;let e=o?new Date(Date.now()+o*1e3).toUTCString():void 0,t={path:this.refreshTokenCookiePath??"/"};e&&(t.expires=new Date(e)),this.refreshTokenCookieSameSite&&(t.sameSite=this.refreshTokenCookieSameSite),this.refreshTokenCookieDomain&&(t.domain=this.refreshTokenCookieDomain),this.refreshTokenCookieHttpOnly==!0&&(t.httpOnly=!0),this.refreshTokenCookieSecure==!0&&(t.secure=!0),s.cookies.set(this.refreshTokenCookieName,i,t)}requireGetParam(s,i){if(!s.url.searchParams.get(i))return{ok:!1,error:"invalid_request",error_description:i+" is required"}}requireBodyParam(s,i){if(!(i in s))return{ok:!1,error:"invalid_request",error_description:i+" is required"}}getAuthorizeQuery(s){let i=this.requireGetParam(s,"response_type");if(i)return{error:i};if(i=this.requireGetParam(s,"client_id"),i)return{error:i};if(i=this.requireGetParam(s,"redirect_uri"),i)return{error:i};if(i=this.requireGetParam(s,"state"),i)return{error:i};const o=s.url.searchParams.get("response_type")??"",e=s.url.searchParams.get("client_id")??"",t=s.url.searchParams.get("redirect_uri")??"",n=s.url.searchParams.get("scope")??void 0,a=s.url.searchParams.get("state")??"",c=s.url.searchParams.get("code_challenge")??void 0,l=s.url.searchParams.get("code_challenge_method")??void 0;return{query:{response_type:o,client_id:e,redirect_uri:t,scope:n,state:a,code_challenge:c,code_challenge_method:l},error:{error:"Unknown error",error_description:"Unknown error",ok:!0}}}async getMfaChallengeQuery(s){let i=new S;await i.loadData(s);const o=i.toObject();let e=this.requireBodyParam(o,"client_id");if(e)return{error:e};if(e=this.requireBodyParam(o,"challenge_type"),e)return{error:e};if(e=this.requireBodyParam(o,"mfa_token"),e)return{error:e};if(e=this.requireBodyParam(o,"authenticator_id"),e)return{error:e};const t=o.client_id??"",n=o.challenge_type??"",a=o.mfa_token??"",c=o.authenticator_id??"",l=o.client_secret??void 0;return{query:{client_id:t,client_secret:l,challenge_type:n,mfa_token:a,authenticator_id:c},error:{error:"Unknown error",error_description:"Unknown error",ok:!0}}}async mfaAuthenticators(s){var n;const i=(n=s.request.headers.get("authorization"))==null?void 0:n.split(" ");if(!i||i.length!=2)return{error:"access_denied",error_description:"Invalid authorization header"};const o=i[1],e=await this.authServer.mfaAuthenticatorsEndpoint(o);if(e.authenticators)return e.authenticators;const t=r.CrossauthError.fromOAuthError(e.error??"server_error");return{error:t.oauthErrorCode,error_description:t.message}}async mfaChallenge(s){let i=await this.getMfaChallengeQuery(s);if(!i.query)return i.error;let o=i.query;return await this.authServer.mfaChallengeEndpoint(o.mfa_token,o.client_id,o.client_secret,o.challenge_type,o.authenticator_id)}getClientIdAndSecret(s,i){let o=s.client_id,e=s.client_secret;const t=i.request.headers.get("authorization");if(t){let n,a;const c=t.split(" ");if(c.length==2&&c[0].toLocaleLowerCase()=="basic"){const h=u.Crypto.base64Decode(c[1]).split(":",2);h.length==2&&(n=h[0],a=h[1])}n==null||a==null?r.CrossauthLogger.logger.warn(r.j({msg:"Ignoring malform authenization header "+t})):(o=n,e=a)}return{client_id:o,client_secret:e}}async applyUserCode(s,i,o){var e,t,n;try{const a=await this.authServer.deviceEndpoint({userCode:s,user:o});if(a.error)return{ok:!1,completed:!1,retryAllowed:!1,error:a.error,error_description:a.error_description};if(!a.client_id)return r.CrossauthLogger.logger.error(r.j({msg:"No client id found for user code",userCodeHash:u.Crypto.hash(s),ip:i.request.referrer,username:(e=i.locals.user)==null?void 0:e.username})),{ok:!1,completed:!1,retryAllowed:!1,error:"server_error",error_description:"No client id found for user code"};if(a.error=="access_denied")return r.CrossauthLogger.logger.error(r.j({msg:"Incorrect user code given",userCodeHash:u.Crypto.hash(s),ip:i.request.referrer,username:(t=i.locals.user)==null?void 0:t.username})),this.authServer.userCodeThrottle>0&&await(h=>new Promise(d=>setTimeout(d,h)))(this.authServer.userCodeThrottle),{ok:!1,completed:!1,retryAllowed:!0,error:a.error,error_description:a.error_description};if(a.error=="expired_token")return r.CrossauthLogger.logger.error(r.j({msg:"Expired user code",userCodeHash:u.Crypto.hash(s),ip:i.request.referrer,username:(n=i.locals.user)==null?void 0:n.username})),{ok:!1,completed:!1,retryAllowed:!1,error:a.error,error_description:a.error_description};const c=await this.clientStorage.getClientById(a.client_id);return a.scopeAuthorizationNeeded?{ok:!0,completed:!1,retryAllowed:!0,authorizationNeeded:{user:o,client_id:a.client_id,client_name:c.client_name,scope:a.scope,scopes:a.scope?a.scope.split(" "):[],csrfToken:i.locals.csrfToken},user:i.locals.user,csrfToken:i.locals.csrfToken,user_code:s}:{ok:!0,completed:!0,retryAllowed:!1,user:i.locals.user,csrfToken:i.locals.csrfToken}}catch(a){const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug(r.j({err:c})),r.CrossauthLogger.logger.error(r.j({msg:c.message,cerr:c})),{ok:!1,completed:!1,retryAllowed:!0,error:c.oauthErrorCode,error_description:c.message}}}baseEndpoint(s){return{user:s.locals.user,csrfToken:s.locals.csrfToken}}async storeSessionData(s,i,o){var e,t,n,a;if(this.svelteKitServer.sessionServer){let c=(e=this.svelteKitServer.sessionServer)==null?void 0:e.getSessionCookieValue(s);c?await((n=this.svelteKitServer.sessionAdapter)==null?void 0:n.updateSessionData(s,o,i)):c=await((t=this.svelteKitServer.sessionServer)==null?void 0:t.createAnonymousSession(s,{[o]:i}))}else await((a=this.svelteKitServer.sessionAdapter)==null?void 0:a.updateSessionData(s,o,i))}async redirectError(s,i,o){throw s?this.redirect(302,s+"?error="+encodeURIComponent(i)+"&error_description="+encodeURIComponent(o)):this.error(500,o)}}async function M(p,s,i){return r.CrossauthLogger.logger.debug(r.j({err:i})),r.CrossauthLogger.logger.error(r.j({cerr:i})),m.json({ok:!1,status:i.httpStatus,errorMessage:i.message,errorMessages:i.messages,errorCode:i.code,errorCodeName:i.codeName},{status:i.httpStatus})}async function Z(p,s,i){var o;throw(o=p.oAuthClient)==null?void 0:o.error(i.httpStatus,i.message)}function b(p){let s;if(p)try{s=JSON.parse(u.Crypto.base64Decode(p.split(".")[1]))}catch(i){const o=r.CrossauthError.asCrossauthError(i);r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({msg:"Couldn't decode token",cerr:o}))}return s}async function q(p,s,i,o,e){let t={ok:!0,...p};return s.jwtTokens.includes("id")&&(t.id_payload=p.id_payload??b(p.id_token)),m.json(t)}function I(p,s){var i;if(p.access_token)try{if(p.access_token&&s.includes("access")){const o=P.jwtDecode(p.access_token),e=o.jti?o.jti:o.sid?o.sid:"",t=e?u.Crypto.hash(e):void 0;r.CrossauthLogger.logger.debug(r.j({msg:"Got access token",accessTokenHash:t}))}}catch(o){r.CrossauthLogger.logger.debug(r.j({err:o}))}if(p.id_token)try{if(p.id_token&&s.includes("id")){const o=p.id_payload??P.jwtDecode(p.id_token);if(o){const e=o.jti?o.jti:o.sid?o.sid:"",t=e?u.Crypto.hash(e):void 0;r.CrossauthLogger.logger.debug(r.j({msg:"Got id token",idTokenHash:t}))}}}catch(o){r.CrossauthLogger.logger.debug(r.j({err:o}))}if(p.refresh_token&&s.includes("refresh"))try{if(p.refresh_token){const o=(i=P.jwtDecode(p.refresh_token))==null?void 0:i.jti,e=o?u.Crypto.hash(o):void 0;r.CrossauthLogger.logger.debug(r.j({msg:"Got refresh token",refreshTokenHash:e}))}}catch(o){r.CrossauthLogger.logger.debug(r.j({err:o}))}}async function R(p,s,i){if(!s.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot update session data if not using sessions");let o=p.expires_in;if(!o&&p.access_token&&s.jwtTokens.includes("access")){const n=P.jwtDecode(p.access_token);n.exp&&(o=n.exp)}if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"OAuth server did not return an expiry for the access token");const e=Date.now()+o*1e3;let t={...p,expires_at:e};if("id_token"in p){let n=p.id_payload??b(p.id_token);n&&(t.id_payload=n)}await s.storeSessionData(i,t)}async function rr(p,s,i,o,e){if(p.error){const t=r.CrossauthError.fromOAuthError(p.error,p.error_description);return s.errorFn(s.server,i,t)}I(p,s.jwtTokens);try{if(p.access_token||p.id_token||p.refresh_token){await R(p,s,i);const t=p.id_payload??b(p.id_token);t&&await e(i,t)}if(!o)return s.redirect(302,s.authorizedUrl)}catch(t){if(C.isSvelteKitError(t)||C.isSvelteKitRedirect(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.debug(r.j({cerr:n,msg:"Error receiving tokens"})),s.errorFn(s.server,i,n)}}async function er(p,s,i,o,e){if(p.error){const t=r.CrossauthError.fromOAuthError(p.error,p.error_description);return s.errorFn(s.server,i,t)}I(p,s.jwtTokens);try{if(p.access_token||p.id_token||p.refresh_token){await R(p,s,i);const t=p.id_payload??b(p.id_token);t&&await e(i,t)}return m.json({ok:!0,...p})}catch(t){if(C.isSvelteKitError(t)||C.isSvelteKitRedirect(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.debug(r.j({cerr:n,msg:"Error receiving tokens"})),s.errorFn(s.server,i,n)}}async function sr(p,s,i,o,e){if(p.error)return{ok:!1,error:p.error,error_description:p.error_description};I(p,s.jwtTokens);try{(p.access_token||p.id_token||p.refresh_token)&&await R(p,s,i);let t={ok:!0,...p};return s.jwtTokens.includes("id")&&(t.id_payload=p.id_payload??b(p.id_token)),t.id_payload&&await e(i,t.id_payload),t}catch(t){if(C.isSvelteKitError(t)||C.isSvelteKitRedirect(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.debug(r.j({cerr:n,msg:"Error receiving tokens"})),{ok:!1,error:n.oauthErrorCode,error_description:n.message}}}async function or(p,s,i,o){if(p.error)return{ok:!1,error:p.error,error_description:p.error_description};I(p,s.jwtTokens);try{let e={ok:!0,...p};return s.jwtTokens.includes("id")&&(e.id_payload=p.id_payload??b(p.id_token)),e}catch(e){if(C.isSvelteKitError(e)||C.isSvelteKitRedirect(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.debug(r.j({cerr:t,msg:"Error receiving tokens"})),{ok:!1,error:t.oauthErrorCode,error_description:t.message}}}class j extends u.OAuthClientBackend{constructor(s,i,o){if(super(i,o),this.sessionDataName="oauth",this.receiveTokenFn=q,this.errorFn=M,this.loginUrl="/login",this.validFlows=[r.OAuthFlows.All],this.authorizedUrl="",this.autoRefreshActive={},this.loginProtectedFlows=[],this.tokenResponseType="sendJson",this.errorResponseType="sendJson",this.bffEndpoints=[],this.bffEndpointName="bff",this.tokenEndpoints=[],this.bffMaxTries=1,this.bffSleepMilliseconds=500,this.jwtTokens=["access","id","refresh"],this.testMiddleware=!1,this.testEvent=void 0,this.authorizationCodeFlowEndpoint={get:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use load not get");return this.errorFn(this.server,e,t)}try{if(!this.validFlows.includes(r.OAuthFlows.AuthorizationCode)){const d=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return this.errorFn(this.server,e,d)}if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Need session server or adapter for authorization code flow");let t=e.url.searchParams.get("scope")??void 0;t==""&&(t=void 0);const n=this.randomValue(this.stateLength),a={scope:t,state:n};await this.storeSessionData(e,a);const{url:c,error:l,error_description:h}=await this.startAuthorizationCodeFlow(n,t);if(l||!c){const d=r.CrossauthError.fromOAuthError(l??"server_error",h);return await this.errorFn(this.server,e,d)}throw this.oauthLogFetch?r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect",url:c})):r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect"})),this.redirect(302,c)}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),this.errorFn(this.server,e,n)}},load:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad"){const t=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return{ok:!1,error:t.oauthErrorCode,error_description:t.message}}try{if(!this.validFlows.includes(r.OAuthFlows.AuthorizationCode)){const d=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return{ok:!1,error:d.oauthErrorCode,error_description:d.message}}if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Need session server or adapter for authorization code flow");let t=e.url.searchParams.get("scope")??void 0;t==""&&(t=void 0);const n=this.randomValue(this.stateLength),a={scope:t,state:n};await this.storeSessionData(e,a);const{url:c,error:l,error_description:h}=await this.startAuthorizationCodeFlow(n,t);if(l||!c){const d=r.CrossauthError.fromOAuthError(l??"server_error",h);return{ok:!1,error:d.oauthErrorCode,error_description:d.message}}throw this.oauthLogFetch?r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect",url:c})):r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect"})),this.redirect(302,c)}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),{ok:!1,error:n.oauthErrorCode,error_description:n.message}}}},this.authorizationCodeFlowWithPKCEEndpoint={get:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use load not get");return this.errorFn(this.server,e,t)}try{if(!this.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)){const g=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return this.errorFn(this.server,e,g)}if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Need session server or adapter for authorization code flow");let t=e.url.searchParams.get("scope")??void 0;t==""&&(t=void 0);const n=this.randomValue(this.stateLength),{codeChallenge:a,codeVerifier:c}=await this.codeChallengeAndVerifier(),l={scope:t,state:n,codeChallenge:a,codeVerifier:c};await this.storeSessionData(e,l);const{url:h,error:d,error_description:f}=await this.startAuthorizationCodeFlow(n,t,a,!0);if(d||!h){const g=r.CrossauthError.fromOAuthError(d??"server_error",f);return await this.errorFn(this.server,e,g)}throw this.oauthLogFetch?r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect",url:h})):r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect"})),this.redirect(302,h)}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),m.json({error:n.oauthErrorCode,error_description:n.message},{status:n.httpStatus})}},load:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use get not load");return{ok:!1,error:t.oauthErrorCode,error_description:t.message}}try{if(!this.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)){const g=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return{ok:!1,error:g.oauthErrorCode,error_description:g.message}}if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Need session server or adapter for authorization code flow");let t=e.url.searchParams.get("scope")??void 0;t==""&&(t=void 0);const n=this.randomValue(this.stateLength),{codeChallenge:a,codeVerifier:c}=await this.codeChallengeAndVerifier(),l={scope:t,state:n,codeChallenge:a,codeVerifier:c};await this.storeSessionData(e,l);const{url:h,error:d,error_description:f}=await this.startAuthorizationCodeFlow(n,t,a,!0);if(d||!h){const g=r.CrossauthError.fromOAuthError(d??"server_error",f);return{ok:!1,error:g.oauthErrorCode,error_description:g.message}}throw this.oauthLogFetch?r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect",url:h})):r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect"})),this.redirect(302,h)}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),{ok:!1,error:n.oauthErrorCode,error_description:n.message}}}},this.redirectUriEndpoint={get:async e=>{var t;if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const n=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use load not get");return this.errorFn(this.server,e,n)}try{if(!(this.validFlows.includes(r.OAuthFlows.AuthorizationCode)||this.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)||this.validFlows.includes(r.OAuthFlows.OidcAuthorizationCode))){const f=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flows are not supported");return this.errorFn(this.server,e,f)}r.CrossauthLogger.logger.debug(r.j({msg:"redirectUriEndpoint, token response type "+this.tokenResponseType}));const n=e.url.searchParams.get("code")??"",a=e.url.searchParams.get("state")??void 0,c=e.url.searchParams.get("error")??void 0,l=e.url.searchParams.get("error")??void 0,h=await((t=this.server.sessionAdapter)==null?void 0:t.getSessionData(e,this.sessionDataName));if((h==null?void 0:h.state)!=a)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"State does not match");const d=this.errorIfIdTokenInvalid(await this.redirectEndpoint(n,h==null?void 0:h.scope,h==null?void 0:h.codeVerifier,c,l));if(d.error)return this.errorFn(this.server,e,r.CrossauthError.fromOAuthError(d.error,d.error_description));if(d.error){const f=r.CrossauthError.fromOAuthError(d.error,d.error_description);return await this.errorFn(this.server,e,f)}return await this.receiveTokenFn(d,this,e,!1,this.setEventLocalsUser)}catch(n){if(C.isSvelteKitRedirect(n)||C.isSvelteKitError(n))throw n;const a=r.CrossauthError.asCrossauthError(n);return r.CrossauthLogger.logger.debug({err:n}),r.CrossauthLogger.logger.error({cerr:n}),this.errorFn(this.server,e,a)}},load:async e=>{var t;if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad"){const n=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use get not load");return{ok:!1,error:n.oauthErrorCode,error_description:n.message}}try{if(!(this.validFlows.includes(r.OAuthFlows.AuthorizationCode)||this.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)||this.validFlows.includes(r.OAuthFlows.OidcAuthorizationCode))){const g=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flows are not supported");return{ok:!1,error:g.oauthErrorCode,error_description:g.message}}const n=e.url.searchParams.get("code")??"",a=e.url.searchParams.get("state")??void 0,c=e.url.searchParams.get("error")??void 0,l=e.url.searchParams.get("error")??void 0,h=await((t=this.server.sessionAdapter)==null?void 0:t.getSessionData(e,this.sessionDataName));if((h==null?void 0:h.state)!=a)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"State does not match");const d=this.errorIfIdTokenInvalid(await this.redirectEndpoint(n,h==null?void 0:h.scope,h==null?void 0:h.codeVerifier,c,l));if(d.error)return{ok:!1,error:d.error,error_description:d.error_description};if(d.error){const g=r.CrossauthError.fromOAuthError(d.error,d.error_description);return{ok:!1,error:g.oauthErrorCode,error_description:g.message}}const f=await this.receiveTokenFn(d,this,e,!1,this.setEventLocalsUser);return f instanceof Response?{ok:!1,error:"server_error",error_description:"When using load, receiveTokenFn should return an object not a Response"}:f==null?{ok:!1,error:"server_error",error_description:"No response received from receiveTokenFn"}:f.error?{ok:!1,error:f.error,error_description:f.error_description}:{...f}}catch(n){if(C.isSvelteKitRedirect(n)||C.isSvelteKitError(n))throw n;const a=r.CrossauthError.asCrossauthError(n);return r.CrossauthLogger.logger.debug({err:n}),r.CrossauthLogger.logger.error({cerr:n}),{ok:!1,error:a.oauthErrorCode,error_description:a.message}}}},this.clientCredentialsFlowEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const a=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,a)}let t;try{if(!this.validFlows.includes(r.OAuthFlows.ClientCredentials)){const l=new r.CrossauthError(r.ErrorCode.Unauthorized,"Client credentials flow is not supported");return this.errorFn(this.server,e,l)}var n=new S;await n.loadData(e),t=n.toObject();const a=this.errorIfIdTokenInvalid(await this.clientCredentialsFlow(t==null?void 0:t.scope));if(a.error){const l=r.CrossauthError.fromOAuthError(a.error,a.error_description);return await this.errorFn(this.server,e,l)}const c=await this.receiveTokenFn(a,this,e,!1,this.setEventLocalsUser);return c instanceof Response?c:this.pack(c)}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:a}),r.CrossauthLogger.logger.error({cerr:a}),this.errorFn(this.server,e,c)}},actions:{default:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use post not load");let t;try{if(!this.validFlows.includes(r.OAuthFlows.ClientCredentials))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Client credentials flow is not supported");var n=new S;await n.loadData(e),t=n.toObject();const a=this.errorIfIdTokenInvalid(await this.clientCredentialsFlow(t==null?void 0:t.scope));if(a.error)throw r.CrossauthError.fromOAuthError(a.error,a.error_description);return await this.receiveTokenFn(a,this,e,!1,this.setEventLocalsUser)??{}}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:a}),r.CrossauthLogger.logger.error({cerr:a}),{ok:!1,error:c.oauthErrorCode,error_description:c.message}}}}},this.refreshTokenFlowEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const a=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,a)}let t;try{if(!this.validFlows.includes(r.OAuthFlows.RefreshToken)){const h=new r.CrossauthError(r.ErrorCode.Unauthorized,"Refresh token flow is not supported");return this.errorFn(this.server,e,h)}var n=new S;if(await n.loadData(e),t=n.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(e))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(h){if(C.isSvelteKitError(h)||C.isSvelteKitRedirect(h))throw h;const d=new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present");return this.errorFn(this.server,e,d)}let a=t.refresh_token;if(!a&&this.server.sessionAdapter){const h=await this.server.sessionAdapter.getSessionData(e,this.sessionDataName);if(!(h!=null&&h.refresh_token)){const d=new r.CrossauthError(r.ErrorCode.BadRequest,"No refresh token in session or in parameters");return this.errorFn(this.server,e,d)}a=h.refresh_token}if(!a){const h=new r.CrossauthError(r.ErrorCode.BadRequest,"No refresh token supplied");return this.errorFn(this.server,e,h)}const c=this.errorIfIdTokenInvalid(await this.refreshTokenFlow(a)),l=await this.receiveTokenFn(c,this,e,!1,this.setEventLocalsUser);if(c&&l instanceof Response)return l;throw new r.CrossauthError(r.ErrorCode.UnknownError,"Receive token function did not return a Response")}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:a}),r.CrossauthLogger.logger.error({cerr:a}),this.errorFn(this.server,e,c)}},actions:{default:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use post not load");let t;try{if(!this.validFlows.includes(r.OAuthFlows.RefreshToken)){const h=new r.CrossauthError(r.ErrorCode.Unauthorized,"Refresh token flow is not supported");return this.errorFn(this.server,e,h)}var n=new S;if(await n.loadData(e),t=n.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(e))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(h){throw C.isSvelteKitError(h)||C.isSvelteKitRedirect(h)?h:new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present")}let a=t.refresh_token;if(!a&&this.server.sessionAdapter){const h=await this.server.sessionAdapter.getSessionData(e,this.sessionDataName);if(!(h!=null&&h.refresh_token))throw new r.CrossauthError(r.ErrorCode.BadRequest,"No refresh token in session or in parameters");a=h.refresh_token}if(!a)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No refresh token supplied");const c=this.errorIfIdTokenInvalid(await this.refreshTokenFlow(a)),l=await this.receiveTokenFn(c,this,e,!1,this.setEventLocalsUser)??{};if(l instanceof Response)throw new r.CrossauthError(r.ErrorCode.Configuration,"Refresh token flow should return an object not Response");return l}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:a}),r.CrossauthLogger.logger.error({cerr:a}),{ok:!1,error:c.oauthErrorCode,error_description:c.message}}}}},this.refreshTokensIfExpiredEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,t)}return this.pack(await this.refreshTokens(e,"post",!0))},actions:{default:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use post not load");return this.refreshTokens(e,"page",!0)}}},this.autoRefreshTokensIfExpiredEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,t)}return this.pack(await this.refreshTokens(e,"silent",!0))}},this.autoRefreshTokensEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,t)}return this.pack(await this.refreshTokens(e,"silent",!1))}},this.startDeviceCodeFlowEndpoint={actions:{default:async e=>await this.startDeviceCodeFlow_internal(e)},post:async e=>{const t=await this.startDeviceCodeFlow_internal(e);if(t.error){const n=r.CrossauthError.fromOAuthError(t.error,t.error_description);return m.json(t,{status:n.httpStatus})}return m.json(t)}},this.pollDeviceCodeFlowEndpoint={actions:{default:async e=>{const t=await this.pollDeviceCodeFlow_internal(e);return t instanceof Response?this.unpack(t):t??{}}},post:async e=>{const t=await this.pollDeviceCodeFlow_internal(e);if(t instanceof Response)return t;if(t==null)return new Response(null,{status:204});if(t.error){const n=r.CrossauthError.fromOAuthError(t.error,t.error_description);return m.json(t,{status:n.httpStatus})}return m.json(t)}},this.passwordFlowEndpoint={post:async e=>await this.passwordFlow_post(e,(t,n)=>this.passwordPost(t,n)),actions:{password:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordPost(t,n)),passwordOtp:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordOtp(t,n)),passwordOob:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordOob(t,n))}},this.passwordOtpEndpoint={post:async e=>await this.passwordFlow_post(e,(t,n)=>this.passwordOtp(t,n)),actions:{default:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordOtp(t,n))}},this.passwordOobEndpoint={post:async e=>await this.passwordFlow_post(e,(t,n)=>this.passwordOob(t,n)),actions:{default:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordOob(t,n))}},this.deleteTokensEndpoint={post:async e=>{var t,n;try{return await this.deleteSessionData(e),m.json({ok:!0})}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),m.json({ok:!1,user:(t=this.server.sessionAdapter)==null?void 0:t.getUser(e),csrfToken:(n=this.server.sessionAdapter)==null?void 0:n.getCsrfToken(e),errorCode:c.code,errorCodeName:c.codeName,errorMessage:c.message},{status:c.httpStatus})}},actions:{default:async e=>{var t,n;try{return await this.deleteSessionData(e),{ok:!0}}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),{ok:!1,user:(t=this.server.sessionAdapter)==null?void 0:t.getUser(e),csrfToken:(n=this.server.sessionAdapter)==null?void 0:n.getCsrfToken(e),errorCode:c.code,errorCodeName:c.codeName,errorMessage:c.message}}}}},this.bffEndpoint={post:async e=>await this.bff(e),get:async e=>await this.bff(e),put:async e=>await this.bff(e),head:async e=>await this.bff(e),options:async e=>await this.bff(e),delete:async e=>await this.bff(e),patch:async e=>await this.bff(e),actions:{get:async e=>await this.unpack(await this.bff(e)),post:async e=>await this.unpack(await this.bff(e))}},this.allBffEndpoint={post:async e=>await this.allBff(e),get:async e=>await this.allBff(e),put:async e=>await this.allBff(e),head:async e=>await this.allBff(e),options:async e=>await this.allBff(e),delete:async e=>await this.allBff(e),patch:async e=>await this.allBff(e),actions:{get:async e=>await this.unpack(await this.allBff(e,{method:"GET"})),gpostet:async e=>await this.unpack(await this.allBff(e,{method:"POST"})),put:async e=>await this.unpack(await this.allBff(e,{method:"PUT"})),options:async e=>await this.unpack(await this.allBff(e,{method:"OPTIONS"})),delete:async e=>await this.unpack(await this.allBff(e,{method:"DELETE"})),patch:async e=>await this.unpack(await this.allBff(e,{method:"PATCH"}))}},this.accessTokenEndpoint={post:async e=>await this.tokens(e,"access_token"),actions:{default:async e=>await this.tokens(e,"access_token")}},this.haveAccessTokenEndpoint={post:async e=>await this.tokensResponse(e,"have_access_token"),actions:{default:async e=>await this.tokens(e,"have_access_token")}},this.refreshTokenEndpoint={post:async e=>await this.tokensResponse(e,"refresh_token"),actions:{default:async e=>await this.tokens(e,"refresh_token")}},this.haveRefreshTokenEndpoint={post:async e=>await this.tokensResponse(e,"have_refresh_token"),actions:{default:async e=>await this.tokens(e,"have_refresh_token")}},this.idTokenEndpoint={post:async e=>await this.tokensResponse(e,"id_token"),actions:{default:async e=>await this.tokens(e,"id_token")}},this.haveIdTokenEndpoint={post:async e=>await this.tokensResponse(e,"have_id_token"),actions:{default:async e=>await this.tokens(e,"have_id_token")}},this.tokensEndpoint={post:async e=>await this.tokensResponse(e,this.tokenEndpoints),actions:{default:async e=>await this.tokens(e,this.tokenEndpoints)}},this.server=s,u.setParameter("sessionDataName",u.ParamType.String,this,o,"OAUTH_SESSION_DATA_NAME"),u.setParameter("tokenResponseType",u.ParamType.String,this,o,"OAUTH_TOKEN_RESPONSE_TYPE"),u.setParameter("errorResponseType",u.ParamType.String,this,o,"OAUTH_ERROR_RESPONSE_TYPE"),u.setParameter("loginUrl",u.ParamType.String,this,o,"LOGIN_URL"),u.setParameter("bffEndpointName",u.ParamType.String,this,o,"OAUTH_BFF_ENDPOINT_NAME"),u.setParameter("bffBaseUrl",u.ParamType.String,this,o,"OAUTH_BFF_BASEURL"),u.setParameter("redirect_uri",u.ParamType.String,this,o,"OAUTH_REDIRECTURI",!0),u.setParameter("authorizedUrl",u.ParamType.String,this,o,"AUTHORIZED_URL",!1),u.setParameter("validFlows",u.ParamType.JsonArray,this,o,"OAUTH_validFlows"),u.setParameter("bffMaxTries",u.ParamType.Number,this,o,"OAUTH_BFF_MAX_RETRIES"),u.setParameter("bffSleepMilliseconds",u.ParamType.Number,this,o,"OAUTH_BFF_SLEEP_MILLISECONDS"),u.setParameter("jwtTokens",u.ParamType.JsonArray,this,o,"OAUTH_JWT_TOKENS"),this.bffEndpointName&&!this.bffEndpointName.startsWith("/")&&(this.bffEndpointName="/"+this.bffEndpointName),this.bffEndpointName&&this.bffEndpointName.endsWith("/")&&(this.bffEndpointName=this.bffEndpointName.substring(0,this.bffEndpointName.length-1)),this.bffBaseUrl&&this.bffBaseUrl.endsWith("/")&&(this.bffBaseUrl=this.bffBaseUrl.substring(0,this.bffBaseUrl.length-1)),o.redirect&&(this.redirect=o.redirect),o.error&&(this.error=o.error),this.validFlows.length==1&&this.validFlows[0]==r.OAuthFlows.All)this.validFlows=r.OAuthFlows.allFlows();else if(!r.OAuthFlows.areAllValidFlows(this.validFlows))throw new r.CrossauthError(r.ErrorCode.Configuration,"Invalid flows specificied in "+this.validFlows.join(","));try{new URL(this.redirect_uri??"")}catch{throw new r.CrossauthError(r.ErrorCode.Configuration,"Invalid redirect Uri "+this.redirect_uri)}if(o.tokenEndpoints&&(this.tokenEndpoints=o.tokenEndpoints),this.bffEndpointName.endsWith("/")&&(this.bffEndpointName=this.bffEndpointName.substring(0,this.bffEndpointName.length-1)),o.bffEndpoints&&(this.bffEndpoints=o.bffEndpoints.map(e=>({...e,methodsString:e.methods.map(t=>t)}))),this.bffEndpoints)for(let e of this.bffEndpoints)e.url.startsWith("/")||(e.url="/"+e.url);if(this.loginProtectedFlows.length==1&&this.loginProtectedFlows[0]==r.OAuthFlows.All)this.loginProtectedFlows=this.validFlows;else if(!r.OAuthFlows.areAllValidFlows(this.loginProtectedFlows))throw new r.CrossauthError(r.ErrorCode.Configuration,"Invalid flows specificied in "+this.loginProtectedFlows.join(","));if(this.tokenResponseType=="custom"&&!o.receiveTokenFn)throw new r.CrossauthError(r.ErrorCode.Configuration,"Token response type of custom selected but receiveTokenFn not defined");if(this.tokenResponseType=="custom"&&o.receiveTokenFn?this.receiveTokenFn=o.receiveTokenFn:this.tokenResponseType=="sendJson"?this.receiveTokenFn=q:this.tokenResponseType=="sendInPage"?this.receiveTokenFn=or:this.tokenResponseType=="saveInSessionAndLoad"?this.receiveTokenFn=sr:this.tokenResponseType=="saveInSessionAndRedirect"?this.receiveTokenFn=rr:this.tokenResponseType=="saveInSessionAndReturn"&&(this.receiveTokenFn=er),(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="saveInSessionAndRedirect")&&this.authorizedUrl=="")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is"+this.tokenResponseType+", must provide authorizedUrl");if((this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="saveInSessionAndRedirect")&&this.server.sessionAdapter==null)throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is"+this.tokenResponseType+", must activate the session server");if(this.errorResponseType=="custom"&&!o.errorFn)throw new r.CrossauthError(r.ErrorCode.Configuration,"Error response type of custom selected but errorFn not defined");if(this.errorResponseType=="custom"&&o.errorFn?this.errorFn=o.errorFn:this.errorResponseType=="sendJson"?this.errorFn=M:this.errorResponseType=="svelteKitError"&&(this.errorFn=Z),!o.redirect)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide the SvelteKit redirect function");if(!o.error&&this.errorResponseType=="svelteKitError")throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide the SvelteKit error function");if(this.loginProtectedFlows.length>0&&this.loginUrl=="")throw new r.CrossauthError(r.ErrorCode.Configuration,"loginUrl must be set if protecting oauth endpoints");this.hook=async({event:e})=>{if(r.CrossauthLogger.logger.debug(r.j({msg:"OAuth hook, user "+e.locals.user})),e.locals.user||!s.sessionAdapter)return;let t=await s.sessionAdapter.getSessionData(e,this.sessionDataName),n=!1;if(t&&t.id_payload){let a=t.expires_at;a&&a>Date.now()&&t.id_payload.sub&&(r.CrossauthLogger.logger.debug(r.j({msg:"ID token is valid"})),await this.setEventLocalsUser(e,t.id_payload),e.locals.user&&(n=!0))}if(!n&&t&&t.refresh_token){r.CrossauthLogger.logger.debug(r.j({msg:"No ID token found but refresh token found - attemping refresh flow"}));const a=await this.refreshTokens(e,"silent",!1);if(a!=null&&a.ok)await this.setEventLocalsUser(e,t.id_payload);else{const c=a instanceof Response||a==null?"server_error":a.error??"server_error",l=a instanceof Response||a==null?"Unknown error":a.error_description??"Unknown error",h=r.CrossauthError.fromOAuthError(c,l);r.CrossauthLogger.logger.debug(r.j({err:h})),r.CrossauthLogger.logger.warn(r.j({msg:"Error refreshing token",cerr:h}))}}this.testMiddleware&&(this.testEvent=e)}}async setEventLocalsUser(s,i){let o;s.locals.idTokenPayload=i;try{o=await this.userCreationFn(i,this.userStorage,this.userMatchField,this.idTokenMatchField),s.locals.user=o,s.locals.authType=o?"oidc":void 0,r.CrossauthLogger.logger.debug(r.j({msg:"Set locals.user to "+(o?o==null?void 0:o.username:"undefined")}))}catch(e){r.CrossauthLogger.logger.error(r.j({cerr:e})),s.locals.user=void 0,s.locals.authType=void 0}}async passwordPost(s,i){var o;try{let e=await this.passwordFlow(i.username,i.password,i.scope);if(e.error=="mfa_required"&&e.mfa_token&&this.validFlows.includes(r.OAuthFlows.PasswordMfa)){const t=e.mfa_token;let n=i.scope;if(n==""&&(n=void 0),e=this.errorIfIdTokenInvalid(await this.passwordMfa(t,n,s)),e.error)throw r.CrossauthError.fromOAuthError(e.error,e.error_description);return e}else if(e.error)throw r.CrossauthError.fromOAuthError(e.error,e.error_description);return e}catch(e){if(C.isSvelteKitError(e)||C.isSvelteKitRedirect(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.error(r.j({msg:"Error receiving token",cerr:t,user:(o=this.server.sessionAdapter)==null?void 0:o.getUser(s)})),r.CrossauthLogger.logger.debug(r.j({err:e})),{error:t.oauthErrorCode,error_description:t.message}}}async passwordMfa(s,i,o){const e=await this.mfaAuthenticators(s);if(e.error||!e.authenticators||!Array.isArray(e.authenticators)||e.authenticators.length==0||e.authenticators.length>1&&!e.authenticators[0].active)return{error:e.error??"server_error",error_description:e.error_description??"Unexpected error getting MFA authenticators"};const t=e.authenticators[0];if(t.authenticator_type=="otp"){const a=await this.mfaOtpRequest(s,t.id);if(a.error||a.challenge_type!="otp"){const c=r.CrossauthError.fromOAuthError(a.error??"server_error",a.error_description??"Invalid response from MFA OTP challenge");return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),{error:c.oauthErrorCode,error_description:c.message}}return{scope:i,mfa_token:s,challenge_type:a.challenge_type}}else if(t.authenticator_type=="oob"){const a=await this.mfaOobRequest(s,t.id);if(a.error||a.challenge_type!="oob"||!a.oob_code||a.binding_method!="prompt"){const c=r.CrossauthError.fromOAuthError(a.error??"server_error",a.error_description??"Invalid response from MFA OOB challenge");return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),{error:c.oauthErrorCode,error_description:c.message}}return{scope:i,mfa_token:s,oob_channel:t.oob_channel,challenge_type:a.challenge_type,binding_method:a.binding_method,oob_code:a.oob_code,name:t.name}}const n=new r.CrossauthError(r.ErrorCode.UnknownError,"Unsupported MFA type "+t.authenticator_type+" returned");return{error:n.oauthErrorCode,error_description:n.message}}async passwordOtp(s,i){let o=i.scope;o==""&&(o=void 0);const e=this.errorIfIdTokenInvalid(await this.mfaOtpComplete(i.mfa_token,i.otp,o));if(e.error){const t=r.CrossauthError.fromOAuthError(e.error,e.error_description??"Error completing MFA");return{error:t.oauthErrorCode,error_description:t.message}}return e}async passwordOob(s,i){var t;let o=i.scope;o==""&&(o=void 0);const e=this.errorIfIdTokenInvalid(await this.mfaOobComplete(i.mfa_token,i.oob_code,i.binding_code,o));return e.error?(r.CrossauthLogger.logger.warn(r.j({msg:"Error completing MFA",user:(t=this.server.sessionAdapter)==null?void 0:t.getUser(s),hashedMfaToken:i.mfa_token?u.Crypto.hash(i.mfa_token):void 0})),{error:e.error,error_description:e.error_description}):e}async refresh(s,i,o,e,t){if(!t||!e)return s!="silent"?await this.receiveTokenFn({},this,i,!0,this.setEventLocalsUser):void 0;if(!o||t<=Date.now()){if(i.locals.sessionId&&this.autoRefreshActive[i.locals.sessionId])return;try{i.locals.sessionId&&(this.autoRefreshActive[i.locals.sessionId]=!0);const n=this.errorIfIdTokenInvalid(await this.refreshTokenFlow(e));if(!n.error&&!n.access_token&&(n.error="server_error",n.error_description="Unexpectedly did not receive error or access token"),!n.error){const l=await this.receiveTokenFn(n,this,i,s=="silent",this.setEventLocalsUser);if(s!="silent")return l}if(s!="silent"){const l=r.CrossauthError.fromOAuthError(n.error??"server_error",n.error_description);return s=="page"?this.errorFn(this.server,i,l):{error:l.oauthErrorCode,error_description:l.message}}let a=n.expires_in;if(!a&&n.access_token){const l=P.jwtDecode(n.access_token);l.exp&&(a=l.exp)}if(!a)throw new r.CrossauthError(r.ErrorCode.BadRequest,"OAuth server did not return an expiry for the access token");const c=new Date().getTime()+a*1e3;return{access_token:n.access_token,refresh_token:n.refresh_token,expires_in:n.expires_in,expires_at:c,error:n.error,error_description:n.error_description}}catch(n){if(C.isSvelteKitRedirect(n)||C.isSvelteKitError(n))throw n;if(r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n,msg:"Failed refreshing access token"})),s!="silent"){const a=r.CrossauthError.asCrossauthError(n);return s=="page"?this.errorFn(this.server,i,a):{error:a.oauthErrorCode,error_description:a.message}}return{error:"server_error",error_description:"Failed refreshing access token"}}finally{i.locals.sessionId&&i.locals.sessionId in this.autoRefreshActive&&delete this.autoRefreshActive[i.locals.sessionId]}}}async refreshTokens(s,i,o){try{if(!this.server.sessionAdapter)return{ok:!1,error:"server_error",error_description:"Refresh tokens if expired or silent refresh only available if sessions are enabled"};if(this.server.sessionAdapter.csrfProtectionEnabled()&&!this.server.sessionAdapter.getCsrfToken(s))return{ok:!1,error:"access_denied",error_description:"No CSRF token found"};const e=await this.server.sessionAdapter.getSessionData(s,this.sessionDataName);if(!(e!=null&&e.refresh_token)){if(i=="silent")return new Response(null,{status:204});throw new r.CrossauthError(r.ErrorCode.InvalidSession,"No tokens found in session")}let t=await this.refresh(i,s,o,e.refresh_token,e.expires_at);if(t&&"id_token"in t&&(t=this.errorIfIdTokenInvalid(t)),i=="silent"){if(t instanceof Response)throw new r.CrossauthError(r.ErrorCode.Configuration,"Unexpected error: refresh: mode is silent but didn't receive an object");return{ok:!0,expires_at:t==null?void 0:t.expires_at}}else if(i=="post"){if(t==null)return this.receiveTokenFn({},this,s,!1,this.setEventLocalsUser);if(t!=null){if(t instanceof Response)return t;throw new r.CrossauthError(r.ErrorCode.Configuration,"refreshTokenFn for post should return Response not object")}}}catch(e){if(C.isSvelteKitRedirect(e)||C.isSvelteKitError(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),i=="page"?this.errorFn(this.server,s,t):{ok:!1,error:t.oauthErrorCode,error_description:t.message}}}async passwordFlow_post(s,i){if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,s,t)}let o;try{if(!(this.validFlows.includes(r.OAuthFlows.Password)||this.validFlows.includes(r.OAuthFlows.PasswordMfa))){const a=new r.CrossauthError(r.ErrorCode.Unauthorized,"Password flow is not supported");return this.errorFn(this.server,s,a)}var e=new S;if(await e.loadData(s),o=e.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(a){if(C.isSvelteKitError(a)||C.isSvelteKitRedirect(a))throw a;const c=new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present");return this.errorFn(this.server,s,c)}const t=this.errorIfIdTokenInvalid(await i(s,o));if(!t)throw new r.CrossauthError(r.ErrorCode.UnknownError,"Password flow returned no data");if(t.error)return{ok:!1,...t};const n=await this.receiveTokenFn(t,this,s,!1,this.setEventLocalsUser);if(t&&n instanceof Response)return n;throw new r.CrossauthError(r.ErrorCode.UnknownError,"Receive token function did not return a Response")}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),this.errorFn(this.server,s,n)}}async passwordFlow_action(s,i){if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use post not load");let o;try{if(!(this.validFlows.includes(r.OAuthFlows.Password)||this.validFlows.includes(r.OAuthFlows.PasswordMfa))){const a=new r.CrossauthError(r.ErrorCode.Unauthorized,"Password and Password MFA flows are not supported");return this.errorFn(this.server,s,a)}var e=new S;if(await e.loadData(s),o=e.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(a){throw C.isSvelteKitError(a)||C.isSvelteKitRedirect(a)?a:new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present")}const t=await i(s,o);if(!t)throw new r.CrossauthError(r.ErrorCode.UnknownError,"Password flow returned no data");if(t.error)return{ok:!1,...t};if(t.challenge_type){if(!this.validFlows.includes(r.OAuthFlows.PasswordMfa)){const a=new r.CrossauthError(r.ErrorCode.Unauthorized,"Password MFA flow is not supported");return this.errorFn(this.server,s,a)}return t}const n=await this.receiveTokenFn(t,this,s,!1,this.setEventLocalsUser)??{};if(n instanceof Response)throw new r.CrossauthError(r.ErrorCode.Configuration,"Refresh token flow should return an object not Response");return n}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),{ok:!1,error:n.oauthErrorCode,error_description:n.message}}}async bff(s,i={}){var e;try{if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Session server must be instantiated to use bff()");if(!this.server.oAuthClient)throw new r.CrossauthError(r.ErrorCode.Configuration,"OAuth Client not found");if(!this.bffBaseUrl)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set bffBaseUrl to use bff()");if(!this.bffEndpointName)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set bffEndpointName to use bff()");let t=i.url;if(!t){if(!s.url.pathname.startsWith(this.bffEndpointName))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Attempt to call BFF url with the wrong prefix");const n=s.url.pathname.substring(this.bffEndpointName.length);let a=((e=s.url.searchParams)==null?void 0:e.toString())??void 0;a&&a!=""&&(a="?"+a),t=new URL(this.bffBaseUrl+n+a)}i.headers||(i.headers=new Headers);for(let n=0;n<this.bffMaxTries;++n){n>0&&await new Promise(d=>setTimeout(d,this.bffSleepMilliseconds));const a=await this.server.sessionAdapter.getSessionData(s,this.sessionDataName);if(!a){if(n==this.bffMaxTries)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No access token found");continue}let c=a.access_token;if(a&&a.access_token){const d=await this.refresh("silent",s,!0,a.refresh_token,a.expires_at);if(d instanceof Response)throw new r.CrossauthError(r.ErrorCode.Configuration,"Expected object when refreshing tokens, not Response");if(d!=null&&d.access_token)c=d.access_token;else if(d!=null&&d.error)continue}i.headers.set("accept","application/json"),i.headers.set("content-type","application/json"),c&&i.headers.set("authorization","Bearer "+c);let l,h;if(s.request.body){var o=new S;await o.loadData(s),h=o.toObject()}if(r.CrossauthLogger.logger.debug(r.j({msg:"Calling BFF URL",url:t,method:s.request.method})),h?l=await fetch(t,{headers:i.headers,method:i.method??s.request.method,body:JSON.stringify(h??"{}")}):l=await fetch(t,{headers:i.headers,method:i.method??s.request.method}),l.status==401){if(n<this.bffMaxTries-1)continue;return l}else return l}return new Response(null,{status:401})}catch(t){if(C.isSvelteKitError(t)||C.isSvelteKitRedirect(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:n}),r.CrossauthLogger.logger.error({cerr:n}),m.json({error:n.oauthErrorCode,error_description:n.message},{status:n.httpStatus})}}async unpack(s){if(s.status==204)return{status:204,body:{}};try{return{status:s.status,body:await s.json()}}catch(i){if(C.isSvelteKitError(i)||C.isSvelteKitRedirect(i))throw i;const o=r.CrossauthError.asCrossauthError(i);return r.CrossauthLogger.logger.debug({err:o}),r.CrossauthLogger.logger.error({cerr:o}),{status:s.status,body:{},error:o.oauthErrorCode,error_description:o.message}}}pack(s){if(s instanceof Response)return s;let i=200;return(s==null?void 0:s.error)=="access_denied"?i=401:s!=null&&s.error?i=500:s||(i=204),m.json(s??null,{status:i})}async allBff(s,i={}){try{if(r.CrossauthLogger.logger.debug(r.j({msg:"Called allBff",url:s.url.toString()})),!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Session server must be instantiated to use bff()");if(!this.server.oAuthClient)throw new r.CrossauthError(r.ErrorCode.Configuration,"OAuth Client not found");if(!this.bffBaseUrl)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set bffBaseUrl to use bff()");if(!this.bffEndpointName)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set bffEndpointName to use bff()");if(!this.bffEndpoints||this.bffEndpoints.length==0)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Invalid BFF endpoint");if(!s.url.pathname.startsWith(this.bffEndpointName))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Attempt to call BFF url with the wrong prefix");const o=s.url.pathname.substring(this.bffEndpointName.length);let e;for(let t=0;t<this.bffEndpoints.length;++t){let n=this.bffEndpoints[t];if(n.matchSubUrls){let a=n.url,c=n.url;if(c.endsWith("/")||(c+="/"),n.methodsString.includes(s.request.method)&&(o.startsWith(c)||o==a)){e=t;break}}else{let a=n.url;if(n.methodsString.includes(s.request.method)&&o==a){e=t;break}}}if(e!=null)return await this.bff(s,i);throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Illegal BFF URL called "+s.url.toString())}catch(o){if(C.isSvelteKitError(o)||C.isSvelteKitRedirect(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug({err:e}),r.CrossauthLogger.logger.error({cerr:e}),m.json({error:e.oauthErrorCode,error_description:e.message},{status:e.httpStatus})}}tokenPayload(s,i,o,e){return s in i?o?{ok:!0}:e?s+"_payload"in i?i[s+"_payload"]:b(i[s]):i[s]:o?{ok:!1}:void 0}async tokens(s,i){try{let o=new S(!0);await o.loadData(s);const e=o.getAsBoolean("decode")??!0;if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Session server must be instantiated to use bff()");if(!this.server.oAuthClient)throw new r.CrossauthError(r.ErrorCode.Configuration,"OAuth Client not found");if(!this.tokenEndpoints||this.tokenEndpoints.length==0)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No tokens have been made available");let t=Array.isArray(i)?i:[i];const n=await this.server.sessionAdapter.getSessionData(s,this.sessionDataName);if(!n)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No access token found");let a={},c,l=!1;for(let h of t){if(!this.tokenEndpoints.includes(h))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Token type "+h+" may not be returned");l=!1;let d=h;h.startsWith("have_")&&(d=h.replace("have_",""),l=!0);const f=d.replace("_token",""),g=e&&this.jwtTokens.includes(f);let E=this.tokenPayload(d,n,l,g);l?a[h]=E.ok:E&&(a[h]=E),c=a[h]}return Array.isArray(i)?{status:200,body:a}:c?l?{status:200,body:typeof c=="boolean"?{ok:c}:c}:{status:200,body:c}:i.startsWith("have_")?{status:200,body:{ok:!1}}:{status:204}}catch(o){if(C.isSvelteKitError(o)||C.isSvelteKitRedirect(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug({err:e}),r.CrossauthLogger.logger.error({cerr:e}),{status:e.httpStatus,body:{error:e.oauthErrorCode,error_description:e.message}}}}async tokensResponse(s,i){const o=await this.tokens(s,i);return o.body?m.json(o.body,{status:o.status}):m.json(null,{status:o.status})}async startDeviceCodeFlow_internal(s){let i;try{if(!this.validFlows.includes(r.OAuthFlows.DeviceCode))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Device code flow is not supported");var o=new S;if(await o.loadData(s),i=o.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(c){throw C.isSvelteKitError(c)||C.isSvelteKitRedirect(c)?c:new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present")}let e=i.scope;e==""&&(e=void 0);let t=this.authServerBaseUrl;t.endsWith("/")||(t+="/"),t+=this.deviceAuthorizationUrl;const n=await this.startDeviceCodeFlow(t,e);let a;return n.verification_uri_complete&&await $.toDataURL(n.verification_uri_complete).then(c=>{a=c}).catch(c=>{r.CrossauthLogger.logger.debug(r.j({err:c})),r.CrossauthLogger.logger.warn(r.j({msg:"Couldn't generate verification URL QR Code"}))}),a?{verification_uri_qrdata:a,...n}:n}catch(e){if(C.isSvelteKitRedirect(e)||C.isSvelteKitError(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug({err:e}),r.CrossauthLogger.logger.error({cerr:e}),{error:t.oauthErrorCode,error_description:t.message}}}async pollDeviceCodeFlow_internal(s){let i;try{if(!this.validFlows.includes(r.OAuthFlows.DeviceCode))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Device code flow is not supported");var o=new S;if(await o.loadData(s),i=o.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(n){throw C.isSvelteKitError(n)||C.isSvelteKitRedirect(n)?n:new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present")}let e=i.device_code;if(!e)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No device code given when polling for user authorization");const t=this.errorIfIdTokenInvalid(await this.pollDeviceCodeFlow(e));if(t.access_token&&!t.error)return await this.receiveTokenFn(t,this,s,!1,this.setEventLocalsUser);{if(t.error=="authorization_pending")return{ok:!0,...t};let n=t.error??"server_error",a=t.error_description??"Didn't receive an access token";const c=r.CrossauthError.fromOAuthError(n,a);return this.errorFn(this.server,s,c)}}catch(e){if(C.isSvelteKitRedirect(e)||C.isSvelteKitError(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug({err:e}),r.CrossauthLogger.logger.error({cerr:e}),this.errorFn(this.server,s,t)}}async deleteSessionData(s){var i;if(this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(o){if(C.isSvelteKitError(o)||C.isSvelteKitRedirect(o))throw o;const e=new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present");return this.errorFn(this.server,s,e)}await((i=this.server.sessionAdapter)==null?void 0:i.deleteSessionData(s,this.sessionDataName))}async storeSessionData(s,i){var o,e,t,n;if(this.server.sessionServer){let a=(o=this.server.sessionServer)==null?void 0:o.getSessionCookieValue(s);a?await((t=this.server.sessionAdapter)==null?void 0:t.updateSessionData(s,this.sessionDataName,i)):a=await((e=this.server.sessionServer)==null?void 0:e.createAnonymousSession(s,{[this.sessionDataName]:i}))}else await((n=this.server.sessionAdapter)==null?void 0:n.updateSessionData(s,this.sessionDataName,i))}errorIfIdTokenInvalid(s){return s.id_token&&this.jwtTokens.includes("id"),s}}class tr{}class H extends u.OAuthResourceServer{constructor(s,i={}){if(super(s,i),this.errorBody={},this.protectedEndpoints={},this.protectedEndpointPrefixes=[],this.sessionDataName="oauth",this.tokenLocations=["header"],u.setParameter("errorBody",u.ParamType.Json,this,i,"OAUTH_RESSERVER_ACCESS_DENIED_BODY"),u.setParameter("tokenLocations",u.ParamType.JsonArray,this,i,"OAUTH_TOKEN_LOCATIONS"),u.setParameter("sessionDataName",u.ParamType.String,this,i,"OAUTH_SESSION_DATA_NAME"),this.userStorage=i.userStorage,this.sessionAdapter=i.sessionAdapter,i.protectedEndpoints){const o=/^[!#\$%&'\(\)\*\+,\.\/a-zA-Z\[\]\^_`-]+/;for(const[e,t]of Object.entries(i.protectedEndpoints)){if(!e.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"protected endpoints must be absolute paths without the protocol and hostname");t.scope&&t.scope.forEach(n=>{if(!o.test(n))throw new r.CrossauthError(r.ErrorCode.Configuration,"Illegal characters in scope "+n)})}this.protectedEndpoints={...i.protectedEndpoints};for(let e in i.protectedEndpoints){let t=this.protectedEndpoints[e];t.suburls==!0&&(e.endsWith("/")||(e+="/",this.protectedEndpoints[e]=t),this.protectedEndpointPrefixes.push(e))}}i.protectedEndpoints&&(this.hook=async({event:o})=>{var c,l;const e=o.url.pathname;let t=!1,n="";if(e in this.protectedEndpoints)t=!0,n=e;else for(let h of this.protectedEndpointPrefixes)e.startsWith(h)&&(t=!0),n=h;if(!t)return;const a=await this.authorized(o);if(!(o.locals.user&&o.locals.authType=="cookie"&&this.protectedEndpoints[n].acceptSessionAuthorization!=!0)){if(!a){o.locals.authError="access_denied",o.locals.authErrorDescription="No access token";const h=this.authenticateHeader(o);return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json","WWW-Authenticate":h},status:401})}if(!a.authorized){const h=this.authenticateHeader(o);return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json","WWW-Authenticate":h},status:401})}}if(a){if(o.locals.accessTokenPayload=a.tokenPayload,o.locals.user=a.user,(c=a.tokenPayload)!=null&&c.scope)if(Array.isArray(a.tokenPayload.scope)){let h=[];for(let d of a.tokenPayload.scope)typeof d=="string"&&h.push(d);o.locals.scope=h}else typeof a.tokenPayload.scope=="string"&&(o.locals.scope=a.tokenPayload.scope.split(" "));if(this.protectedEndpoints[n].scope){for(let h of this.protectedEndpoints[n].scope??[])if(!o.locals.scope||!o.locals.scope.includes(h)&&this.protectedEndpoints[n].acceptSessionAuthorization!=!0){r.CrossauthLogger.logger.warn(r.j({msg:"Access token does not have sufficient scope",username:(l=o.locals.user)==null?void 0:l.username,url:o.request.url})),o.locals.scope=void 0,o.locals.accessTokenPayload=void 0,o.locals.user=void 0,o.locals.authError="access_denied",o.locals.authErrorDescription="Access token does not have sufficient scope";const d=this.authenticateHeader(o);return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json","WWW-Authenticate":d},status:401})}}if(o.locals.authType="oauth",o.locals.authError=a==null?void 0:a.error,(a==null?void 0:a.error)=="access_denied"){const h=this.authenticateHeader(o);return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json","WWW-Authenticate":h},status:401})}else if(a!=null&&a.error)return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json"},status:500});o.locals.authErrorDescription=a==null?void 0:a.error_description,r.CrossauthLogger.logger.debug(r.j({msg:"Resource server url",url:o.request.url,authorized:o.locals.accessTokenPayload!=null}))}})}authenticateHeader(s){const i=s.url.pathname;if(i in this.protectedEndpoints){let o="Bearer";return this.protectedEndpoints[i].scope&&(o+=' scope="'+(this.protectedEndpoints[i].scope??[]).join(" ")),o}return""}async authorized(s){try{let i;for(let e of this.tokenLocations)if(e=="header"){const t=await this.tokenFromHeader(s);if(t){i=t;break}}else{const t=await this.tokenFromSession(s);if(t){i=t;break}}let o;if(i){if(i.sub&&this.userStorage){const e=await this.userStorage.getUserByUsername(i.sub);e&&(o=e.user)}else i.sub&&(s.locals.user={id:i.userid??i.sub,username:i.sub,state:i.state??"active"});return{authorized:!0,tokenPayload:i,user:o}}else return{authorized:!1}}catch(i){const o=i;return r.CrossauthLogger.logger.debug(r.j({err:i})),r.CrossauthLogger.logger.error(r.j({cerr:o})),s.locals.authError="server_error",s.locals.authErrorDescription=o.message,{authorized:!1,error:"server_error",error_description:o.message}}}async tokenFromHeader(s){const i=s.request.headers.get("authorization");if(i&&i.startsWith("Bearer ")){const o=i.split(" ");if(o.length==2)return await this.accessTokenAuthorized(o[1])}}async tokenFromSession(s){if(!this.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot get session data if sessions not enabled");const i=await this.sessionAdapter.getSessionData(s,this.sessionDataName);if(i!=null&&i.session_token)return i.expires_at&&i.expires_at<Date.now()?void 0:await this.accessTokenAuthorized(i.session_token)}}function ir(p){return p.admin==!0}const U=class U{constructor({session:s,sessionAdapter:i,apiKey:o,oAuthAuthServer:e,oAuthClient:t,oAuthClients:n,oAuthResServer:a,options:c}){this.loginUrl="/login",this.audience="",this.dummyLoad=async h=>({}),this.dummyActions={},this.dummyBff=async h=>({status:500,body:{error:"Unimplemented"}}),c||(c={}),u.setParameter("loginUrl",u.ParamType.String,this,c,"LOGIN_URL",!1),c.isAdminFn&&(U.isAdminFn=c.isAdminFn);let l={};if(c.authenticators&&(l=c.authenticators),this.userStorage=c.userStorage,s){if(!l)throw new r.CrossauthError(r.ErrorCode.Configuration,"If using session management, must supply authenticators");this.sessionServer=new N(s.keyStorage,l,{...s.options,...c}),this.sessionAdapter=this.sessionServer}else i&&(this.sessionAdapter=i);if(o){if(!this.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must define a user storage if using API keys");this.apiKeyServer=new x(this.userStorage,o.keyStorage,{...c,...o.options})}if(e){let h={};this.loginUrl&&(h.loginUrl=this.loginUrl),this.oAuthAuthServer=new B(this,e.clientStorage,e.keyStorage,l,{...h,...c,...e.options})}if(t&&n)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot specify both oAuthClient and oAuthClients");if(t&&(this.oAuthClient=new j(this,t.authServerBaseUrl,{...c,...t.options})),n){this.oAuthClients=[];for(let h of n)this.oAuthClients.push(new j(this,h.authServerBaseUrl,{...c,...h.options}))}a&&(u.setParameter("audience",u.ParamType.String,this,c,"OAUTH_AUDIENCE",!0),this.oAuthResServer=new H([new u.OAuthTokenConsumer(this.audience,c)],{sessionAdapter:this.sessionAdapter,...a.options,...c})),this.hooks=async({event:h,resolve:d})=>{const f=await this.unresolvedHooks(h);return f instanceof Response?f:await d(f)}}async unresolvedHooks(s){var o,e;s.locals.user=void 0,s.locals.sessionId=void 0,s.locals.csrfToken=void 0,s.locals.authType=void 0,s.locals.scope=void 0;let i=!1;if(this.sessionServer){let t=await this.sessionServer.sessionHook({event:s});if(t.status==302){let a;for(let c of t.headers)c.name=="location"&&(a=c.value);a&&await this.sessionServer.redirect(302,a)}const n=this.userStorage?await this.sessionServer.twoFAHook({event:s}):void 0;if(!(n&&n.twofa)&&!s.locals.user){if(this.apiKeyServer&&await this.apiKeyServer.hook({event:s}),this.oAuthClient&&await this.oAuthClient.hook({event:s}),(o=this.oAuthResServer)!=null&&o.hook){const a=await this.oAuthResServer.hook({event:s});if(a)return a}if(i=!0,!s.locals.user){if(this.sessionServer.isLoginPageProtected(s)){if(r.CrossauthLogger.logger.debug(r.j({msg:"Page is login protected and we don't have credentials"})),this.loginUrl){let a=encodeURIComponent(s.request.url);return new Response(null,{status:302,headers:{location:this.loginUrl+"?next="+a}})}return this.sessionServer.error(401,"Unauthorized")}if(this.sessionServer.isLoginApiProtected(s))return this.sessionServer.error(401,"Unauthorized")}}if(!(n&&n.twofa)&&this.sessionServer.isAdminPageEndpoint(s)&&(!s.locals.user||!U.isAdminFn(s.locals.user)))return this.sessionServer.unauthorizedUrl?new Response(null,{status:302,headers:{location:this.sessionServer.unauthorizedUrl}}):this.sessionServer.error(401,"Unauthorized");if(!(n&&n.twofa)&&this.sessionServer.isAdminApiEndpoint(s)&&(!s.locals.user||!U.isAdminFn(s.locals.user)))return this.sessionServer.error(401,"Unauthorized");if(n!=null&&n.response)return n.response}if(!i&&(this.apiKeyServer&&await this.apiKeyServer.hook({event:s}),this.oAuthClient&&await this.oAuthClient.hook({event:s}),(e=this.oAuthResServer)!=null&&e.hook)){const t=await this.oAuthResServer.hook({event:s});if(t)return t}return s}static isSvelteKitRedirect(s){return typeof s=="object"&&s!=null&&"status"in s&&"location"in s}static isSvelteKitError(s,i){return i?typeof s=="object"&&s!=null&&"status"in s&&"text"in s&&"message"in s&&s.status==i:typeof s=="object"&&s!=null&&"status"in s&&"text"in s&&"message"in s}};U.isAdminFn=ir;let C=U;class V{constructor(s,i){if(this.changePasswordUrl=void 0,this.changeFactor2Url=void 0,this.configureFactor2Url=void 0,this.requestPasswordResetUrl=void 0,this.loginRedirectUrl="/",this.loginUrl="/login",this.signupEndpoint={load:async o=>{var t;return{allowedFactor2:((t=this.sessionServer)==null?void 0:t.allowedFactor2)??[{name:"none",friendlyName:"None"}],...this.baseEndpoint(o)}},actions:{default:async o=>await this.signup(o)}},this.loginEndpoint={load:async o=>({next:o.url.searchParams.get("next")??this.loginRedirectUrl,...this.baseEndpoint(o)}),actions:{login:async o=>{var t;const e=await this.login(o);return(e==null?void 0:e.ok)==!0&&!(e!=null&&e.factor2Required)&&this.sessionServer.redirect(302,((t=e.formData)==null?void 0:t.next)??this.loginRedirectUrl),e&&((e==null?void 0:e.errorCode)==r.ErrorCode.UserNotExist||(e==null?void 0:e.errorCode)==r.ErrorCode.PasswordInvalid)&&(e.error="Username or password is invalid"),e},factor2:async o=>{var t;const e=await this.loginFactor2(o);return(e==null?void 0:e.ok)==!0&&!(e!=null&&e.factor2Required)&&this.sessionServer.redirect(302,((t=e.formData)==null?void 0:t.next)??this.loginRedirectUrl),e}}},this.factor2Endpoint={load:async o=>{const e=await this.requestFactor2(o);return e&&!e.error&&o.url.searchParams.get("error")&&(e.error=o.url.searchParams.get("error")??void 0),e}},this.logoutEndpoint={actions:{default:async o=>await this.logout(o)},load:async o=>({...this.baseEndpoint(o)})},this.changeFactor2Endpoint={actions:{change:async o=>await this.changeFactor2(o),reconfigure:async o=>await this.reconfigureFactor2(o)},load:async o=>{var h;let e=(h=o.locals.user)==null?void 0:h.username;if(!this.isSessionUser(o)||!o.locals.user){const d=await this.sessionServer.getSessionData(o,"factor2change");d!=null&&d.username||this.isSessionUser(o)||(this.sessionServer.unauthorizedUrl&&this.sessionServer.redirect(302,this.sessionServer.unauthorizedUrl),this.sessionServer.error(401,"Unauthorized")),e=d==null?void 0:d.username}let t=this.sessionServer.allowedFactor2??[{name:"none",friendlyName:"None",configurable:!1}],n={},a=o.url.searchParams.get("required"),c;a&&(a=a.toLowerCase(),c=a=="true"||a=="1",c==!0&&(n.required=!0));let l=o.url.searchParams.get("next");return l&&(n.next=l),{allowedFactor2:t,...n,username:e,...this.baseEndpoint(o)}}},this.changePasswordEndpoint={actions:{default:async o=>await this.changePassword(o)},load:async o=>{let e={},t=o.url.searchParams.get("required"),n,a=o.locals.user!=null;if(!a){const l=await this.sessionServer.getSessionData(o,"passwordchange");l!=null&&l.username&&(a=!0)}a||this.sessionServer.redirect(302,this.loginUrl),t&&(t=t.toLowerCase(),n=t=="true"||t=="1",n==!0&&(e.required=!0));let c=o.url.searchParams.get("next");return c&&(e.next=c),{...e,...this.baseEndpoint(o)}}},this.configureFactor2Endpoint={actions:{default:async o=>await this.configureFactor2(o)},load:async o=>({...this.baseEndpoint(o)})},this.deleteUserEndpoint={actions:{default:async o=>await this.deleteUser(o)},load:async o=>({...this.baseEndpoint(o)})},this.resetPasswordEndpoint={actions:{default:async o=>await this.requestPasswordReset(o)},load:async o=>{let e={},t=o.url.searchParams.get("required"),n;return t&&(t=t.toLowerCase(),n=t=="true"||t=="1",n==!0&&(e.required=!0)),{...e,...this.baseEndpoint(o)}}},this.passwordResetTokenEndpoint={actions:{default:async o=>{let e=await this.validatePasswordResetToken(o);if(!(e!=null&&e.user))throw new r.CrossauthError(r.ErrorCode.InvalidToken,"The password reset token is invalid");if(e.user.factor2!=""&&!o.locals.sessionId&&await this.sessionServer.createAnonymousSession(o,{user:{username:e.user.username}}),e!=null&&e.error)return{ok:!1,tokenValidated:!1,error:e==null?void 0:e.error,...this.baseEndpoint(o)};try{return e=await this.resetPassword(o),e}catch(t){const n=r.CrossauthError.asCrossauthError(t);if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{ok:!1,tokenValidated:!1,error:e==null?void 0:e.error,errorCode:n.code,errorCodeName:n.codeName,...this.baseEndpoint(o)}}}},load:async o=>{try{if(o.request.method!="POST"){const e=await this.validatePasswordResetToken(o);if(!(e!=null&&e.user))throw new r.CrossauthError(r.ErrorCode.InvalidToken,"The password reset token is invalid");return e.user.factor2!=""&&!o.locals.sessionId&&await this.sessionServer.createAnonymousSession(o,{user:{username:e.user.username}}),{tokenValidated:(e==null?void 0:e.ok)??!1,error:e==null?void 0:e.error,...this.baseEndpoint(o)}}else return{tokenValidated:!1,...this.baseEndpoint(o)}}catch(e){const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{tokenValidated:!1,error:t.message,errorCode:t.code,errorCodeName:t.codeName,...this.baseEndpoint(o)}}}},this.updateUserEndpoint={actions:{default:async o=>await this.updateUser(o)},load:async o=>({allowedFactor2:this.sessionServer.allowedFactor2??[{name:"none",friendlyName:"None"}],...this.baseEndpoint(o)})},this.verifyEmailTokenEndpoint={load:async o=>{const e=await this.verifyEmail(o);return{...this.baseEndpoint(o),...e}}},this.sessionServer=s,u.setParameter("changePasswordUrl",u.ParamType.String,this,i,"CHANGE_PASSWORD_URL"),u.setParameter("requestPasswordResetUrl",u.ParamType.String,this,i,"REQUEST_PASSWORD_RESET_URL"),u.setParameter("changeFactor2Url",u.ParamType.String,this,i,"CHANGE_FACTOR2_URL"),u.setParameter("configureFactor2Url",u.ParamType.String,this,i,"CONFIGURE_FACTOR2_URL"),u.setParameter("loginRedirectUrl",u.ParamType.JsonArray,this,i,"LOGIN_REDIRECT_URL"),u.setParameter("loginUrl",u.ParamType.JsonArray,this,i,"LOGIN_URL"),i.addToSession&&(this.addToSession=i.addToSession),this.changePasswordUrl&&!this.changePasswordUrl.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"changePasswordUrl must be an absolute path");if(this.requestPasswordResetUrl&&!this.requestPasswordResetUrl.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"requestPasswordResetUrl must be an absolute path");if(this.changeFactor2Url&&!this.changeFactor2Url.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"changeFactor2Url must be an absolute path");if(this.configureFactor2Url&&!this.configureFactor2Url.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"configureFactor2Url must be an absolute path");if(!this.loginUrl.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"loginUrl must be an absolute path")}isSessionUser(s){return s.locals.user!=null&&s.locals.authType=="cookie"}canEditUser(s){return this.isSessionUser(s)||this.sessionServer.editUserScope&&s.locals.scope&&s.locals.scope.includes(this.sessionServer.editUserScope)}async login(s){let i;try{var o=new S;await o.loadData(s),i=o.toObject();const e=o.get("username")??"",t=o.getAsBoolean("persist")??!1;i.next.includes("/__data.json")&&(i.next=i.next.substring(0,i.next.indexOf("/__data.json")));let n=i.next??this.loginRedirectUrl;if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"Username field may not be empty");let a=this.addToSession?this.addToSession(s,i):{};if(this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const c=this.sessionServer.getSessionCookieValue(s);let{sessionCookie:l,csrfCookie:h,user:d}=await this.sessionServer.sessionManager.login(e,o.toObject(),a,t);if(r.CrossauthLogger.logger.debug(r.j({msg:"Login: set session cookie "+l.name+" opts "+JSON.stringify(l.options),user:e})),s.cookies.set(l.name,l.value,u.toCookieSerializeOptions(l.options)),r.CrossauthLogger.logger.debug(r.j({msg:"Login: set csrf cookie "+h.name+" opts "+JSON.stringify(l.options),user:e})),this.sessionServer.enableCsrfProtection&&(s.cookies.set(h.name,h.value,u.toCookieSerializeOptions(h.options)),s.locals.csrfToken=await this.sessionServer.sessionManager.createCsrfFormOrHeaderValue(h.value)),c)try{await this.sessionServer.sessionManager.deleteSession(c)}catch(f){r.CrossauthLogger.logger.warn(r.j({msg:"Couldn't delete session ID from database",hashOfSessionId:this.sessionServer.getHashOfSessionId(s)})),r.CrossauthLogger.logger.debug(r.j({err:f}))}if(d.state==r.UserState.passwordChangeNeeded){if(!this.changePasswordUrl)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set changePasswordUrl in session server");this.sessionServer.redirect(302,this.changePasswordUrl+"?required=true&next="+encodeURIComponent("login?next="+n))}else{if(d.state==r.UserState.passwordResetNeeded)throw new r.CrossauthError(r.ErrorCode.PasswordResetNeeded,"Please click on the link we sent you to reset your password");if(d.state==r.UserState.passwordAndFactor2ResetNeeded)throw new r.CrossauthError(r.ErrorCode.PasswordResetNeeded,"Please click on the link we sent you to reset your password");if(this.sessionServer.allowedFactor2.length>0&&d.state==r.UserState.factor2ResetNeeded||!this.sessionServer.allowedFactor2Names.includes(d.factor2?d.factor2:"none")){if(!this.changeFactor2Url)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set changeFactor2Url in session server");this.sessionServer.redirect(302,this.changeFactor2Url+"?required=true&next="+encodeURIComponent("login?next="+n))}else(!d.factor2||d.factor2=="")&&(s.locals.user=d)}return{user:d,formData:i,factor2Required:d.factor2&&d.factor2!="",next:n,ok:!0}}catch(e){if(typeof e=="object"&&e!=null&&"status"in e&&"location"in e)throw e;let t=r.CrossauthError.asCrossauthError(e,"Couldn't log in");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,ok:!1,formData:i,errorCode:t.code,errorCodeName:t.codeName}}}async loginWithUser(s,i,o){const e=o.locals.sessionId,t=new S;await t.loadData(o);let n=this.addToSession?this.addToSession(o,t.toObject()):{},{sessionCookie:a,csrfCookie:c,csrfFormOrHeaderValue:l}=await this.sessionServer.sessionManager.login("",{},n,void 0,s,i);if(r.CrossauthLogger.logger.debug(r.j({msg:"Login: set session cookie "+a.name+" opts "+JSON.stringify(a.options),user:s.username})),o.cookies.set(a.name,a.value,u.toCookieSerializeOptions(a.options)),r.CrossauthLogger.logger.debug(r.j({msg:"Login: set csrf cookie "+c.name+" opts "+JSON.stringify(a.options),user:s.username})),this.sessionServer.enableCsrfProtection&&o.cookies.set(c.name,c.value,u.toCookieSerializeOptions(c.options)),o.locals.user=s,o.locals.csrfToken=l,o.locals.sessionId=this.sessionServer.sessionManager.getSessionId(a.value),e)try{await this.sessionServer.sessionManager.deleteSession(e)}catch(h){r.CrossauthLogger.logger.warn(r.j({msg:"Couldn't delete session ID from database",hashOfSessionId:this.sessionServer.getHashOfSessionId(o)})),r.CrossauthLogger.logger.debug(r.j({err:h}))}return{user:s,ok:!0}}async logout(s){try{if(s.locals.sessionId&&await this.sessionServer.sessionManager.logout(s.locals.sessionId),r.CrossauthLogger.logger.debug(r.j({msg:"Logout: clear cookie "+this.sessionServer.sessionManager.sessionCookieName})),s.cookies.delete(this.sessionServer.sessionManager.sessionCookieName,{path:"/"}),this.sessionServer.enableCsrfProtection&&s.cookies.delete(this.sessionServer.sessionManager.csrfCookieName,{path:"/"}),s.locals.sessionId)try{await this.sessionServer.sessionManager.deleteSession(s.locals.sessionId)}catch(i){r.CrossauthLogger.logger.warn(r.j({msg:"Couldn't delete session ID from database",hashOfSessionId:this.sessionServer.getHashOfSessionId(s)})),r.CrossauthLogger.logger.debug(r.j({err:i}))}if(s.locals.sessionId=void 0,s.locals.user=void 0,this.sessionServer.enableCsrfProtection){s.locals.csrfToken=void 0,s.cookies.delete(this.sessionServer.sessionManager.csrfCookieName,{path:"/"});const{csrfCookie:i,csrfFormOrHeaderValue:o}=await this.sessionServer.sessionManager.createCsrfToken();this.sessionServer.setCsrfCookie(i,s),s.locals.csrfToken=o}return{ok:!0}}catch(i){const o=r.CrossauthError.asCrossauthError(i);return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{ok:!1,error:o.message,errorCode:o.code,errorCodeName:o.codeName}}}async signup(s){let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;await o.loadData(s),i=o.toObject();const e=o.get("username")??"";let t;if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"Username field may not be empty");if(i.factor2||(i.factor2=this.sessionServer.allowedFactor2Names[0]),i.factor2&&!this.sessionServer.allowedFactor2Names.includes(i.factor2??"none"))throw new r.CrossauthError(r.ErrorCode.Forbidden,"Illegal second factor "+i.factor2+" requested");(i.factor2=="none"||i.factor2=="")&&(i.factor2=void 0),t=this.sessionServer.createUserFn(s,i,this.sessionServer.userStorage.userEditableFields,this.sessionServer.userAllowedFactor1);let n=this.sessionServer.authenticators[t.factor1].validateSecrets(i);const a=this.sessionServer.authenticators[t.factor1].secretNames();let c={};for(let f in i)if(f.startsWith("repeat_")){const g=f.replace(/^repeat_/,"");a.includes(g)&&(c[g]=i[f])}Object.keys(c).length===0&&(c=void 0),t.state="active",i.factor2&&i.factor2!="none"?t.state="awaitingtwofactor":this.sessionServer.enableEmailVerification&&(t.state="awaitingemailverification");let h=[...this.sessionServer.validateUserFn(t),...n];if(h.length>0)throw new r.CrossauthError(r.ErrorCode.FormEntry,h);let d=!1;try{const{user:f,secrets:g}=await this.sessionServer.userStorage.getUserByUsername(e);await this.sessionServer.sessionManager.authenticators[t.factor1].authenticateUser(f,g,i)}catch(f){r.CrossauthError.asCrossauthError(f).code==r.ErrorCode.TwoFactorIncomplete&&(d=!0)}if(!i.factor2&&!d)return await this.sessionServer.sessionManager.createUser(t,i,c),this.sessionServer.enableEmailVerification?{emailVerificationRequired:!0,user:t,ok:!0,formData:i}:{...await this.login(s),formData:i};{let f;if(d){if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized);f=(await this.sessionServer.sessionManager.repeatTwoFactorSignup(s.locals.sessionId)).userData}else{const g=await this.sessionServer.createAnonymousSession(s),E=this.sessionServer.sessionManager.getSessionId(g);f=(await this.sessionServer.sessionManager.initiateTwoFactorSignup(t,i,E,c)).userData}try{let g={userData:f,username:e,factor2:i.factor2??"none"};return this.sessionServer.enableCsrfProtection&&(g.csrfToken=s.locals.csrfToken),{factor2Data:g,ok:!0,factor2Required:!0,formData:i}}catch(g){r.CrossauthLogger.logger.error(r.j({err:g}));try{this.sessionServer.sessionManager.deleteUserByUsername(e)}catch(E){r.CrossauthLogger.logger.error(r.j({err:E}))}}}return{user:t,formData:i,ok:!0}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't sign up");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,ok:!1,formData:i,errorCode:t.code,errorCodeName:t.codeName}}}async verifyEmail(s){var i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");const o=s.params.token;if(!o)throw new r.CrossauthError(r.ErrorCode.InvalidToken,"Invalid email verification token");const e=await this.sessionServer.sessionManager.applyEmailVerificationToken(o);if(await this.loginWithUser(e,!0,s),s.locals.user){const t=await this.sessionServer.userStorage.getUserById((i=s.locals.user)==null?void 0:i.id);s.locals.user=t.user}return{ok:!0,user:e}}catch(o){const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName}}}async configureFactor2(s){let i,o,e="";try{var t=new S;await t.loadData(s),i=t.toObject();const n=await this.sessionServer.getSessionData(s,"2fa");if(n!=null&&n.factor2)e=n==null?void 0:n.factor2;else throw new r.CrossauthError(r.ErrorCode.BadRequest,"Two factor authentication was not started");if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session active while enabling 2FA. Please enable cookies");let a=await this.sessionServer.sessionManager.completeTwoFactorSetup(i,s.locals.sessionId);return this.sessionServer.enableEmailVerification||await this.loginWithUser(a,!0,s),s.locals.user?{ok:!0,user:a,emailVerificationRequired:this.sessionServer.enableEmailVerification}:await this.loginWithUser(a,!0,s)}catch(n){const a=r.CrossauthError.asCrossauthError(n);let c;try{c=(await this.sessionServer.sessionManager.repeatTwoFactorSignup(s.locals.sessionId??"")).userData}catch{}return c?o={userData:c,csrfToken:s.locals.csrfToken,username:c.username??"",factor2:e}:o={userData:{},csrfToken:s.locals.csrfToken,username:"",factor2:e},r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{ok:!1,error:a.message,errorCode:a.code,errorCodeName:a.codeName,formData:i,factor2Data:o,emailVerificationRequired:this.sessionServer.enableEmailVerification}}}async loginFactor2(s){if(s.locals.user)return{user:s.locals.user,ok:!0};let i;try{var o=new S;await o.loadData(s),i=o.toObject();const e=o.getAsBoolean("persist")??!1,t=s.locals.sessionId;if(!t)throw new r.CrossauthError(r.ErrorCode.Unauthorized);if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);let n=this.addToSession?this.addToSession(s,i):{};const{sessionCookie:a,csrfCookie:c,user:l}=await this.sessionServer.sessionManager.completeTwoFactorLogin(i,t,n,e);return r.CrossauthLogger.logger.debug(r.j({msg:"Login: set session cookie "+a.name+" opts "+JSON.stringify(a.options),user:l==null?void 0:l.username})),s.cookies.set(a.name,a.value,u.toCookieSerializeOptions(a.options)),r.CrossauthLogger.logger.debug(r.j({msg:"Login: set csrf cookie "+c.name+" opts "+JSON.stringify(a.options),user:l==null?void 0:l.username})),s.cookies.set(c.name,c.value,u.toCookieSerializeOptions(c.options)),this.sessionServer.enableCsrfProtection&&(s.locals.csrfToken=await this.sessionServer.sessionManager.createCsrfFormOrHeaderValue(c.value)),s.locals.user=l,{user:l,ok:!0,formData:i}}catch(e){const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:t.message,errorCode:t.code,errorCodeName:t.codeName,formData:i}}}async requestPasswordReset(s){let i;try{var o=new S;await o.loadData(s),i=o.toObject();const e=o.get("email")??"";if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"Email field may not be empty");if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!this.sessionServer.enablePasswordReset)throw new r.CrossauthError(r.ErrorCode.Configuration,"Password reset not enabled");return await this.sessionServer.sessionManager.requestPasswordReset(e),{formData:i,ok:!0}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't log in");return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{error:t.message,errorCode:t.code,errorCodeName:t.codeName,ok:!1,formData:i}}}async validatePasswordResetToken(s){r.CrossauthLogger.logger.debug(r.j({msg:"validatePasswordResetToken "+s.request.method}));try{const i=s.params.token;if(!i)throw new r.CrossauthError(r.ErrorCode.InvalidToken,"Invalid email verification token");return{ok:!0,user:await this.sessionServer.sessionManager.userForPasswordResetToken(i),formData:{token:i}}}catch(i){const o=r.CrossauthError.asCrossauthError(i);return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{ok:!1,error:o.message,errorCode:o.code,errorCodeName:o.codeName}}}async resetPassword(s){r.CrossauthLogger.logger.debug(r.j({msg:"resetPassword"}));let i;try{var o=new S;if(await o.loadData(s),i=o.toObject(),this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!this.sessionServer.enablePasswordReset)throw new r.CrossauthError(r.ErrorCode.Configuration,"Password reset not enabled");const e=s.params.token??"";if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"No token provided");const t=await this.sessionServer.sessionManager.userForPasswordResetToken(e),n=this.sessionServer.authenticators[t.factor1],a=n.secretNames();let c={},l={};for(let f in i)if(f.startsWith("new_")){const g=f.replace(/^new_/,"");a.includes(g)&&(c[g]=i[f])}else if(f.startsWith("repeat_")){const g=f.replace(/^repeat_/,"");a.includes(g)&&(l[g]=i[f])}if(Object.keys(l).length===0&&(l=void 0),n.validateSecrets(c).length>0)throw new r.CrossauthError(r.ErrorCode.PasswordFormat);const d=await this.sessionServer.sessionManager.resetSecret(e,1,c,l);if(d.state==r.UserState.active)return await this.loginWithUser(d,!0,s);{if(!this.changeFactor2Url)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set changeFactor2Url in session server");const f=this.sessionServer.getSessionCookieValue(s),g=this.sessionServer.sessionManager.getSessionId(f??"");throw await this.sessionServer.sessionManager.updateSessionData(g,"factor2change",{username:t.username}),this.sessionServer.redirect(302,this.changeFactor2Url+"?required=true")}}catch(e){if(C.isSvelteKitRedirect(e))throw e;let t=r.CrossauthError.asCrossauthError(e,"Couldn't log in");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,errorCode:t.code,errorCodeName:t.codeName,ok:!1,formData:i}}}async requestFactor2(s){try{if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session cookie present");const i=this.sessionServer.getSessionCookieValue(s),o=this.sessionServer.sessionManager.getSessionId(i??""),e=await this.sessionServer.sessionManager.dataForSessionId(o);if(!(e!=null&&e.pre2fa))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"2FA not initiated");return{ok:!0,csrfToken:s.locals.csrfToken,action:e.pre2fa.url,factor2:e.pre2fa.factor2}}catch(i){let o=r.CrossauthError.asCrossauthError(i,"2FA failed");return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{error:o.message,errorCode:o.code,errorCodeName:o.codeName,ok:!1}}}async changePassword(s){r.CrossauthLogger.logger.debug(r.j({msg:"changePassword"}));let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;await o.loadData(s),i=o.toObject();let e,t=!1;if(!this.isSessionUser(s)||!s.locals.user){const g=await this.sessionServer.getSessionData(s,"passwordchange");if(g!=null&&g.username){if(e=(await this.sessionServer.userStorage.getUserByUsername(g==null?void 0:g.username,{skipActiveCheck:!0,skipEmailVerifiedCheck:!0})).user,t=!0,this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}else throw new r.CrossauthError(r.ErrorCode.Unauthorized)}else if(this.canEditUser(s)){if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);e=s.locals.user}else throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);const n=this.sessionServer.authenticators[e.factor1],a=n.secretNames();let c={},l={},h={};for(let g in i)if(g.startsWith("new_")){const E=g.replace(/^new_/,"");a.includes(E)&&(l[E]=i[g])}else if(g.startsWith("old_")){const E=g.replace(/^old_/,"");a.includes(E)&&(c[E]=i[g])}else if(g.startsWith("repeat_")){const E=g.replace(/^repeat_/,"");a.includes(E)&&(h[E]=i[g])}if(Object.keys(h).length===0&&(h=void 0),n.validateSecrets(l).length>0)throw new r.CrossauthError(r.ErrorCode.PasswordFormat);const f=e.state;try{t&&(e.state="active",await this.sessionServer.userStorage.updateUser({id:e.id,state:e.state})),await this.sessionServer.sessionManager.changeSecrets(e.username,1,l,h,c)}catch(g){const E=r.CrossauthError.asCrossauthError(g);if(r.CrossauthLogger.logger.debug(r.j({err:g})),t)try{await this.sessionServer.userStorage.updateUser({id:e.id,state:f})}catch(w){r.CrossauthLogger.logger.debug(r.j({err:w}))}throw E}return t?await this.loginWithUser(e,!1,s):{ok:!0,formData:i}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't change password");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,ok:!1,errorCode:t.code,errorCodeName:t.codeName,formData:i}}}async deleteUser(s){r.CrossauthLogger.logger.debug(r.j({msg:"deleteUser"}));try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");if(this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!s.locals.user)throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);return await this.sessionServer.userStorage.deleteUserById(s.locals.user.id),s.cookies.delete(this.sessionServer.sessionManager.sessionCookieName,{path:"/"}),s.locals.sessionId=void 0,s.locals.user=void 0,{ok:!0}}catch(i){let o=r.CrossauthError.asCrossauthError(i,"Couldn't delete account");return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{error:o.message,errorCode:o.code,errorCodeName:o.codeName,ok:!1}}}async updateUser(s){r.CrossauthLogger.logger.debug(r.j({msg:"updateUser"}));let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;if(await o.loadData(s),i=o.toObject(),this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!s.locals.user)throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);let e={id:s.locals.user.id,username:s.locals.user.username,state:"active"};e=this.sessionServer.updateUserFn(e,s,i,this.sessionServer.userStorage.userEditableFields);let t=this.sessionServer.validateUserFn(e);if(t.length>0)throw new r.CrossauthError(r.ErrorCode.FormEntry,t);let{emailVerificationTokenSent:n}=await this.sessionServer.sessionManager.updateUser(s.locals.user,e);if(!n){const a=await this.sessionServer.userStorage.getUserById(s.locals.user.id);s.locals.user=a.user}return{ok:!0,formData:i,emailVerificationNeeded:n}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't update account");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,errorCode:t.code,errorCodeName:t.codeName,ok:!1,formData:i,emailVerificationNeeded:!1}}}async changeFactor2(s){var e;r.CrossauthLogger.logger.debug(r.j({msg:"updateUser"}));let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;if(await o.loadData(s),i=o.toObject(),this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);let t=(e=s.locals.user)==null?void 0:e.username;if(!this.isSessionUser(s)||!s.locals.user){const l=await this.sessionServer.getSessionData(s,"factor2change");l!=null&&l.username||this.isSessionUser(s)||(this.sessionServer.unauthorizedUrl&&this.sessionServer.redirect(302,this.sessionServer.unauthorizedUrl),this.sessionServer.error(401,"Unauthorized")),t=l==null?void 0:l.username}let n=s.locals.user;if(!n&&t&&(n=(await this.sessionServer.userStorage.getUserByUsername(t,{skipActiveCheck:!0,skipEmailVerifiedCheck:!0})).user),!n)throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized);let a=i.factor2;if(i.factor2&&!this.sessionServer.allowedFactor2Names.includes(i.factor2))throw new r.CrossauthError(r.ErrorCode.Forbidden,"Illegal second factor "+i.factor2+" requested");if((i.factor2=="none"||i.factor2=="")&&(a=void 0,!s.locals.user))return await this.loginWithUser(n,!0,s);const c=await this.sessionServer.sessionManager.initiateTwoFactorSetup(n,a,s.locals.sessionId);return a?{ok:!0,formData:i,factor2Data:{username:n.username,factor2:a??"",userData:c,csrfToken:s.locals.csrfToken}}:{ok:!0,formData:i}}catch(t){let n=r.CrossauthError.asCrossauthError(t,"Couldn't update account");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1,formData:i}}}async reconfigureFactor2(s){var e;r.CrossauthLogger.logger.debug(r.j({msg:"updateUser"}));let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;if(await o.loadData(s),i=o.toObject(),this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);let t=(e=s.locals.user)==null?void 0:e.username;if(!this.isSessionUser(s)||!s.locals.user){const h=await this.sessionServer.getSessionData(s,"factor2change");h!=null&&h.username||this.isSessionUser(s)||(this.sessionServer.unauthorizedUrl&&this.sessionServer.redirect(302,this.sessionServer.unauthorizedUrl),this.sessionServer.error(401,"Unauthorized")),t=h==null?void 0:h.username}let n=s.locals.user;if(!n&&t&&(n=(await this.sessionServer.userStorage.getUserByUsername(t,{skipActiveCheck:!0,skipEmailVerifiedCheck:!0})).user),!n)throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized);if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized);let a=n.factor2;const c=this.sessionServer.authenticators[a];if(!c||c.secretNames().length==0)throw new r.CrossauthError(r.ErrorCode.BadRequest,"Selected second factor does not have configuration");const l=await this.sessionServer.sessionManager.initiateTwoFactorSetup(n,a,s.locals.sessionId);return{ok:!0,formData:i,factor2Data:{username:n.username,factor2:n.factor2??"",userData:l,csrfToken:s.locals.csrfToken}}}catch(t){let n=r.CrossauthError.asCrossauthError(t,"Couldn't update account");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1,formData:i}}}baseEndpoint(s){return{user:s.locals.user,csrfToken:s.locals.csrfToken}}}async function ar(p,s,i=0,o=10){let e=[];if(i>0)return[];try{const{user:t}=await s.getUserByUsername(p);e.push(t)}catch(t){const n=r.CrossauthError.asCrossauthError(t);if(n.code!=r.ErrorCode.UserNotExist)throw r.CrossauthLogger.logger.debug(r.j({err:n})),n;try{const{user:a}=await s.getUserByEmail(p);e.push(a)}catch(a){const c=r.CrossauthError.asCrossauthError(a);if(c.code!=r.ErrorCode.UserNotExist)throw r.CrossauthLogger.logger.debug(r.j({err:c})),n}}return e}class W{constructor(s,i){this.userSearchFn=ar,this.searchUsersEndpoint={load:async o=>{(!o.locals.user||!C.isAdminFn(o.locals.user))&&this.sessionServer.error(o,401);const e=await this.searchUsers(o);return{...this.baseEndpoint(o),...e}}},this.updateUserEndpoint={actions:{default:async o=>{var n,a,c;const e=await this.getUserFromParam(o);return e.exception||!e.user?{ok:!1,error:((n=e.exception)==null?void 0:n.message)??"Couldn't get user",errorCode:(a=e.exception)==null?void 0:a.code,errorCodeName:(c=e.exception)==null?void 0:c.codeName}:await this.updateUser(e.user,o)}},load:async o=>{(!o.locals.user||!C.isAdminFn(o.locals.user))&&this.sessionServer.error(o,401);let e=this.sessionServer.allowedFactor2??[{name:"none",friendlyName:"None"}];const t=await this.getUserFromParam(o);return t.exception||!t.user?{allowedFactor2:e,editUser:t.user,...this.baseEndpoint(o)}:{allowedFactor2:e,editUser:t.user,...this.baseEndpoint(o)}}},this.changePasswordEndpoint={actions:{default:async o=>{var n,a,c;const e=await this.getUserFromParam(o);return e.exception||!e.user?{ok:!1,error:((n=e.exception)==null?void 0:n.message)??"Couldn't get user",errorCode:(a=e.exception)==null?void 0:a.code,errorCodeName:(c=e.exception)==null?void 0:c.codeName}:await this.changePassword(e.user,o)}},load:async o=>{(!o.locals.user||!C.isAdminFn(o.locals.user))&&this.sessionServer.error(o,401);const e=await this.getUserFromParam(o);if(e.exception||!e.user)return{editUser:e.user,...this.baseEndpoint(o)};let t={},n=o.url.searchParams.get("next");return n&&(t.next=n),{...t,editUser:e.user,...this.baseEndpoint(o)}}},this.createUserEndpoint={load:async o=>{var t;return(!o.locals.user||!C.isAdminFn(o.locals.user))&&this.sessionServer.error(o,401),{allowedFactor2:((t=this.sessionServer)==null?void 0:t.allowedFactor2)??[{name:"none",friendlyName:"None"}],...this.baseEndpoint(o)}},actions:{default:async o=>await this.createUser(o)}},this.deleteUserEndpoint={actions:{default:async o=>await this.deleteUser(o)},load:async o=>{var t,n,a;const e=await this.getUserFromParam(o);return e.exception||!e.user?{error:"User doesn't exist",errorCode:(t=e.exception)==null?void 0:t.code,errorCodeName:(n=e.exception)==null?void 0:n.codeName,...this.baseEndpoint(o)}:{username:(a=e.user)==null?void 0:a.username,...this.baseEndpoint(o)}}},this.sessionServer=s,i.userSearchFn&&(this.userSearchFn=i.userSearchFn)}isSessionUser(s){return s.locals.user!=null&&s.locals.authType=="cookie"}async searchUsers(s,i,o,e){try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");(!s.locals.user||!C.isAdminFn(s.locals.user))&&this.sessionServer.error(401);let t=[],n=[],a=[];if(!o)try{const l=s.url.searchParams.get("skip");l&&(o=parseInt(l))}catch(l){r.CrossauthLogger.logger.warn(r.j({cerr:l,msg:"skip parameter is not an integer"}))}if(o||(o=0),!e)try{const l=s.url.searchParams.get("take");l&&(e=parseInt(l))}catch(l){r.CrossauthLogger.logger.warn(r.j({cerr:l,msg:"take parameter is not an integer"}))}e||(e=10);const c=s.url.searchParams.get("search");return!i&&c!=null&&c!=""&&(i=c),i||(i=""),i.length==0&&(i=void 0),i?(t=await this.userSearchFn(i,this.sessionServer.userStorage,o,e),o>0&&(n=await this.userSearchFn(i,this.sessionServer.userStorage,o-1,1))):(t=await this.sessionServer.userStorage.getUsers(o,e),t.length==e&&(a=await this.sessionServer.userStorage.getUsers(o+e,1))),{ok:!0,users:t,skip:o,take:e,hasPrevious:n.length>0,hasNext:a.length>0,search:i}}catch(t){const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{ok:!1,error:n.message,errorCode:n.code,errorCodeName:n.codeName,hasPrevious:!1,hasNext:!1,skip:o??0,take:e??10,search:i}}}async updateUser(s,i){let o;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var e=new S;if(await e.loadData(i),o=e.toObject(),(!i.locals.user||!C.isAdminFn(i.locals.user))&&this.sessionServer.error(401),this.isSessionUser(i)&&this.sessionServer.enableCsrfProtection&&!i.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const t=s.factor2,n=s.state;s.state=o.state??"active",s=this.sessionServer.updateUserFn(s,i,o,{...this.sessionServer.userStorage.userEditableFields,...this.sessionServer.userStorage.adminEditableFields});const a=s.factor2&&s.factor2!="none"&&s.factor2!=t;if(a&&!(s.state==n||s.state=="factor2ResetNeeded"))throw new r.CrossauthError(r.ErrorCode.BadRequest,"Cannot change both factor2 and state at the same time");a&&(s.state=r.UserState.factor2ResetNeeded,r.CrossauthLogger.logger.warn(r.j({msg:`Setting state for user to ${r.UserState.factor2ResetNeeded}`,username:s.username})));let c=this.sessionServer.validateUserFn(s);if(c.length>0)throw new r.CrossauthError(r.ErrorCode.FormEntry,c);const l=await this.sessionServer.sessionManager.updateUser(s,s,!0,!0);let h;return l.emailVerificationTokenSent?h="An email verification token has been sent to the user":l.passwordResetTokenSent&&(h="A password reset token has been sent to the user"),{ok:!0,formData:o,info:h}}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t,401))throw t;let n=r.CrossauthError.asCrossauthError(t,"Couldn't log in");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1,formData:o}}}async changePassword(s,i){r.CrossauthLogger.logger.debug(r.j({msg:"changePassword"}));let o;try{var e=new S;if(await e.loadData(i),o=e.toObject(),(!i.locals.user||!C.isAdminFn(i.locals.user))&&this.sessionServer.error(401),this.isSessionUser(i)&&this.sessionServer.enableCsrfProtection&&!i.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const t=this.sessionServer.authenticators[s.factor1],n=t.secretNames();let a={},c={},l={};for(let d in o)if(d.startsWith("new_")){const f=d.replace(/^new_/,"");n.includes(f)&&(c[f]=o[d])}else if(d.startsWith("old_")){const f=d.replace(/^old_/,"");n.includes(f)&&(a[f]=o[d])}else if(d.startsWith("repeat_")){const f=d.replace(/^repeat_/,"");n.includes(f)&&(l[f]=o[d])}if(Object.keys(l).length===0&&(l=void 0),Object.keys(a).length===0&&(a=void 0),t.validateSecrets(c).length>0)throw new r.CrossauthError(r.ErrorCode.PasswordFormat);try{await this.sessionServer.sessionManager.changeSecrets(s.username,1,c,l,a)}catch(d){const f=r.CrossauthError.asCrossauthError(d);throw r.CrossauthLogger.logger.debug(r.j({err:d})),f}return{ok:!0,formData:o}}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t,401))throw t;let n=r.CrossauthError.asCrossauthError(t,"Couldn't change password");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1,formData:o}}}async createUser(s){let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;await o.loadData(s),i=o.toObject();const e=o.get("username")??"";let t;if((!s.locals.user||!C.isAdminFn(s.locals.user))&&this.sessionServer.error(401),this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"Username field may not be empty");if(i.factor2||(i.factor2=this.sessionServer.allowedFactor2Names[0]),i.factor2&&!this.sessionServer.allowedFactor2Names.includes(i.factor2??"none"))throw new r.CrossauthError(r.ErrorCode.Forbidden,"Illegal second factor "+i.factor2+" requested");(i.factor2=="none"||i.factor2=="")&&(i.factor2=void 0),t=this.sessionServer.createUserFn(s,i,{...this.sessionServer.userStorage.userEditableFields,...this.sessionServer.userStorage.adminEditableFields},this.sessionServer.adminAllowedFactor1);const n=this.sessionServer.authenticators[t.factor1].secretNames();let a=!0;for(let g of n)!i[g]&&!i["repeat_"+g]&&(a=!1);let c=[],l={};if(a){c=this.sessionServer.authenticators[t.factor1].validateSecrets(i);for(let g in i)if(g.startsWith("repeat_")){const E=g.replace(/^repeat_/,"");n.includes(E)&&(l[E]=i[g])}Object.keys(l).length===0&&(l=void 0)}a?i.factor2!=null&&(t.state=r.UserState.factor2ResetNeeded):i.factor2==null?t.state=r.UserState.passwordResetNeeded:t.state=r.UserState.passwordAndFactor2ResetNeeded;let d=[...this.sessionServer.validateUserFn(t),...c];if(d.length>0)throw new r.CrossauthError(r.ErrorCode.FormEntry,d);const f=await this.sessionServer.sessionManager.createUser(t,i,l,!0,!a);if(!a){let g=i.username;if("user_email"in i&&(g=i.user_email),u.TokenEmailer.validateEmail(g),!g)throw new r.CrossauthError(r.ErrorCode.FormEntry,"No password given but no email address found either");await this.sessionServer.sessionManager.requestPasswordReset(g)}return{ok:!0,user:f,formData:i}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't create user");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,errorCode:t.code,errorCodeName:t.codeName,ok:!1,formData:i}}}async deleteUser(s){if(r.CrossauthLogger.logger.debug(r.j({msg:"deleteUser"})),!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");try{const i=s.params.id;if(!i)throw new r.CrossauthError(r.ErrorCode.BadRequest,"User ID is undefined");if(this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);return(!s.locals.user||!C.isAdminFn(s.locals.user))&&this.sessionServer.error(401),await this.sessionServer.userStorage.deleteUserById(i),{ok:!0}}catch(i){let o=r.CrossauthError.asCrossauthError(i,"Couldn't delete account");return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{error:o.message,errorCode:o.code,errorCodeName:o.codeName,ok:!1}}}baseEndpoint(s){return{user:s.locals.user,csrfToken:s.locals.csrfToken}}async getUserFromParam(s,i="id"){let o=s.params[i];if(!o)return{exception:new r.CrossauthError(r.ErrorCode.BadRequest,"Must give user id")};try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");return{user:(await this.sessionServer.userStorage.getUserById(o,{skipEmailVerifiedCheck:!0,skipActiveCheck:!0})).user}}catch(e){return{exception:r.CrossauthError.asCrossauthError(e)}}}}async function J(p,s,i,o,e){let t=[];if(i>0)return[];try{const n=await s.getClientById(p);t.push(n)}catch(n){const a=r.CrossauthError.asCrossauthError(n);if(a.code!=r.ErrorCode.UserNotExist)throw r.CrossauthLogger.logger.debug(r.j({err:a})),a;try{t=await s.getClientByName(p,e)}catch(c){const l=r.CrossauthError.asCrossauthError(c);if(l.code!=r.ErrorCode.UserNotExist)throw r.CrossauthLogger.logger.debug(r.j({err:l})),a}}return t}class O{constructor(s,i){this.loginUrl="/login",this.clientSearchFn=J,this.validFlows=["all"],this.sessionServer=s,u.setParameter("loginUrl",u.ParamType.JsonArray,this,i,"LOGIN_URL"),i.clientSearchFn&&(this.clientSearchFn=i.clientSearchFn),this.redirect=i.redirect??m.redirect,this.error=i.error??m.error,u.setParameter("validFlows",u.ParamType.JsonArray,this,i,"OAUTH_validFlows"),this.validFlows.length==1&&this.validFlows[0]==r.OAuthFlows.All&&(this.validFlows=r.OAuthFlows.allFlows()),this.valid_flowNames=r.OAuthFlows.flowNames(this.validFlows),i.clientStorage&&(this.clientManager=new u.OAuthClientManager(i)),this.clientStorage=i.clientStorage}async searchClients_internal(s,i,o,e,t){try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");if(!this.sessionServer.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide client storage to use this function");if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));let n=[],a=[],c=[];if(!o)try{const h=s.url.searchParams.get("skip");h&&(o=parseInt(h))}catch(h){r.CrossauthLogger.logger.warn(r.j({cerr:h,msg:"skip parameter is not an integer"}))}if(o||(o=0),!e)try{const h=s.url.searchParams.get("take");h&&(e=parseInt(h))}catch(h){r.CrossauthLogger.logger.warn(r.j({cerr:h,msg:"take parameter is not an integer"}))}e||(e=10);const l=s.url.searchParams.get("search");return!i&&l!=null&&l!=""&&(i=l),i||(i=""),i.length==0&&(i=void 0),i?(n=await this.clientSearchFn(i,this.sessionServer.clientStorage,o,e),o>0&&(a=await this.clientSearchFn(i,this.sessionServer.clientStorage,o-1,1,t))):(n=await this.sessionServer.clientStorage.getClients(o,e,t),n.length==e&&(c=await this.sessionServer.clientStorage.getClients(o+e,1,t))),{ok:!0,clients:n,skip:o,take:e,hasPrevious:a.length>0,hasNext:c.length>0,search:i,clientUserId:t}}catch(n){if(C.isSvelteKitRedirect(n)||C.isSvelteKitRedirect(n))throw n;const a=r.CrossauthError.asCrossauthError(n);return r.CrossauthLogger.logger.debug(r.j({err:a})),r.CrossauthLogger.logger.error(r.j({cerr:a})),{ok:!1,error:a.message,errorCode:a.code,errorCodeName:a.codeName,hasPrevious:!1,hasNext:!1,skip:o??0,take:e??10,search:i,clientUserId:t}}}async loadClient_internal(s){var o,e,t;const i=s.params.client_id;try{if(!i)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID specified");if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");const n=await this.clientStorage.getClientById(i),a=n.userid==null?void 0:await((e=(o=this.sessionServer)==null?void 0:o.userStorage)==null?void 0:e.getUserById(n.userid)),c=(t=a==null?void 0:a.user)==null?void 0:t.username;return{ok:!0,client:n,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames,client_id:i,clientUsername:c}}catch(n){let a=r.CrossauthError.asCrossauthError(n,"Couldn't load client");return r.CrossauthLogger.logger.debug(r.j({err:a})),r.CrossauthLogger.logger.error(r.j({cerr:a})),{error:a.message,errorCode:a.code,errorCodeName:a.codeName,ok:!1,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames,client_id:i}}}async updateClient_internal(s,i){var t,n;let o;try{const a=s.params.client_id;if(!a)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");var e=new S;if(await e.loadData(s),o=e.toObject(),this.sessionServer.enableCsrfProtection&&s.locals.authType=="cookie"&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const c=!o.redirect_uri||o.redirect_uri.trim().length==0?[]:o.redirect_uri.trim().split(/[, ][ \t\n]*/);let l=[];for(let w of c)try{u.OAuthClientManager.validateUri(w)}catch(k){r.CrossauthLogger.logger.error(r.j({err:k})),l.push("["+w+"]")}if(l.length>0)throw new r.CrossauthError(r.ErrorCode.BadRequest,"The following redirect URIs are invalid: "+l.join(" "));let h=[];for(let w of this.validFlows)w in o&&h.push(w);const d={};if(d.client_name=o.client_name,d.confidential=e.getAsBoolean("confidential")??!1,d.valid_flow=h,d.redirect_uri=c,i){let w=o.userid??void 0;if(w&&((t=this.sessionServer)!=null&&t.userStorage)){const{user:k}=await((n=this.sessionServer)==null?void 0:n.userStorage.getUserById(w));w=k.id}d.userid=o.userid?Number(o.userid):null}const f=e.getAsBoolean("resetSecret");if(!this.clientManager)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot call this endpoint as you did not provide a clientStorage");const{client:g,newSecret:E}=await this.clientManager.updateClient(a,d,f);return{ok:!0,client:g,formData:o,plaintextSecret:E&&g.client_secret?g.client_secret:void 0}}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;let c=r.CrossauthError.asCrossauthError(a,"Couldn't update client");return r.CrossauthLogger.logger.debug(r.j({err:c})),r.CrossauthLogger.logger.error(r.j({cerr:c})),{error:c.message,errorCode:c.code,errorCodeName:c.codeName,ok:!1,formData:o}}}async emptyClient_internal(s,i){var e,t,n,a,c,l,h;try{var o=new S;await o.loadData(s);let d;if(i){const E=s.url.searchParams.get("userid");if(E&&((e=this.sessionServer)!=null&&e.userStorage)){const{user:k}=await((t=this.sessionServer)==null?void 0:t.userStorage.getUserById(E));d=k.id}const w=o.get("userid");if(w&&((n=this.sessionServer)!=null&&n.userStorage)){const{user:k}=await((a=this.sessionServer)==null?void 0:a.userStorage.getUserById(w));d=k.id}}else{if(!s.locals.user)throw new r.CrossauthError(r.ErrorCode.Unauthorized);d=s.locals.user.id}if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");const f=d==null?void 0:await((l=(c=this.sessionServer)==null?void 0:c.userStorage)==null?void 0:l.getUserById(d)),g=(h=f==null?void 0:f.user)==null?void 0:h.username;return{ok:!0,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames,clientUserId:d,clientUsername:g}}catch(d){let f=r.CrossauthError.asCrossauthError(d,"Couldn't initialize new client");return r.CrossauthLogger.logger.debug(r.j({err:f})),r.CrossauthLogger.logger.error(r.j({cerr:f})),{error:f.message,errorCode:f.code,errorCodeName:f.codeName,ok:!1,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames}}}async createClient_internal(s,i){var t,n,a,c;let o;try{var e=new S;await e.loadData(s),o=e.toObject();let l;if(i){const w=e.get("userid");if(w&&((t=this.sessionServer)!=null&&t.userStorage)){const{user:k}=await((n=this.sessionServer)==null?void 0:n.userStorage.getUserById(w));l=k.id}}else{if(!s.locals.user)throw new r.CrossauthError(r.ErrorCode.Unauthorized);l=s.locals.user.id}if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");if(l&&await((c=(a=this.sessionServer)==null?void 0:a.userStorage)==null?void 0:c.getUserById(l)),this.sessionServer.enableCsrfProtection&&s.locals.authType=="cookie"&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const h=!o.redirect_uri||o.redirect_uri.trim().length==0?[]:o.redirect_uri.trim().split(/[, ][ \t\n]*/);let d=[];for(let w of h)try{u.OAuthClientManager.validateUri(w)}catch(k){r.CrossauthLogger.logger.error(r.j({err:k})),d.push("["+w+"]")}if(d.length>0)throw new r.CrossauthError(r.ErrorCode.BadRequest,"The following redirect URIs are invalid: "+d.join(" "));let f=[];for(let w of this.validFlows)w in o&&f.push(w);const g={};if(g.client_name=o.client_name,g.confidential=e.getAsBoolean("confidential"),g.valid_flow=f,g.redirect_uri=h,i&&(g.userid=o.userid?Number(o.userid):null),!this.clientManager)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot call this endpoint as you did not provide a clientStorage");return{ok:!0,client:await this.clientManager.createClient(o.client_name,h,f,e.getAsBoolean("confidential")??!1,l),formData:o}}catch(l){if(C.isSvelteKitRedirect(l)||C.isSvelteKitError(l))throw l;let h=r.CrossauthError.asCrossauthError(l,"Couldn't create client");return r.CrossauthLogger.logger.debug(r.j({err:h})),r.CrossauthLogger.logger.error(r.j({cerr:h})),{error:h.message,errorCode:h.code,errorCodeName:h.codeName,ok:!1,formData:o}}}async loadDeleteClient_internal(s){var o,e,t;const i=s.params.client_id;try{if(!i)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID specified");if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");const n=await this.clientStorage.getClientById(i),a=n.userid==null?void 0:await((e=(o=this.sessionServer)==null?void 0:o.userStorage)==null?void 0:e.getUserById(n.userid)),c=(t=a==null?void 0:a.user)==null?void 0:t.username;return{ok:!0,client:n,client_id:i,clientUsername:c}}catch(n){let a=r.CrossauthError.asCrossauthError(n,"Couldn't load client");return r.CrossauthLogger.logger.debug(r.j({err:a})),r.CrossauthLogger.logger.error(r.j({cerr:a})),{error:a.message,errorCode:a.code,errorCodeName:a.codeName,ok:!1,client_id:i}}}async deleteClient_internal(s,i){var o,e;try{if(this.sessionServer.enableCsrfProtection&&s.locals.authType=="cookie"&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const t=s.params.client_id;if(!t)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");const n=await((o=this.clientStorage)==null?void 0:o.getClientById(t));if(!i&&n.userid!=((e=s.locals.user)==null?void 0:e.id))throw this.error(401,"Unauthorized");return await this.clientStorage.deleteClient(t),{ok:!0}}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;let n=r.CrossauthError.asCrossauthError(t,"Couldn't delete client");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1}}}baseEndpoint(s){return{user:s.locals.user,csrfToken:s.locals.csrfToken}}}class G extends O{constructor(s,i){super(s,i),this.searchClientsEndpoint={load:async o=>{const e=await this.searchClients(o);return{...this.baseEndpoint(o),...e}}},this.updateClientEndpoint={load:async o=>{const e=await this.loadClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.updateClient(o)}},this.createClientEndpoint={load:async o=>{const e=await this.emptyClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.createClient(o)}},this.deleteClientEndpoint={load:async o=>{const e=await this.loadDeleteClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.deleteClient(o)}},this.sessionServer=s,u.setParameter("loginUrl",u.ParamType.JsonArray,this,i,"LOGIN_URL"),i.clientSearchFn&&(this.clientSearchFn=i.clientSearchFn),this.redirect=i.redirect,this.error=i.error}async searchClients(s,i,o,e){var t;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));return this.searchClients_internal(s,i,o,e,(t=s.locals.user)==null?void 0:t.id)}async loadClient(s){var i;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));try{const o=s.params.client_id;if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");const e=await((i=this.clientStorage)==null?void 0:i.getClientById(o));if((e==null?void 0:e.userid)!=s.locals.user.id)return this.error(401,"Access denied")}catch(o){if(C.isSvelteKitRedirect(o)||C.isSvelteKitError(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames}}return this.loadClient_internal(s)}async updateClient(s){var i;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));try{const o=s.params.client_id;if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");const e=await((i=this.clientStorage)==null?void 0:i.getClientById(o));if((e==null?void 0:e.userid)!=s.locals.user.id)return this.error(401,"Access denied")}catch(o){if(C.isSvelteKitRedirect(o)||C.isSvelteKitError(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName}}return this.updateClient_internal(s,!1)}async loadDeleteClient(s){var i;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));try{const o=s.params.client_id;if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");const e=await((i=this.clientStorage)==null?void 0:i.getClientById(o));if((e==null?void 0:e.userid)!=s.locals.user.id)return this.error(401,"Access denied")}catch(o){if(C.isSvelteKitRedirect(o)||C.isSvelteKitError(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName}}return this.loadDeleteClient_internal(s)}async deleteClient(s){var i;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));try{const o=s.params.client_id;if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");const e=await((i=this.clientStorage)==null?void 0:i.getClientById(o));if((e==null?void 0:e.userid)!=s.locals.user.id)return this.error(401,"Access denied")}catch(o){if(C.isSvelteKitRedirect(o)||C.isSvelteKitError(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName}}return this.deleteClient_internal(s,!1)}async emptyClient(s){if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));return this.emptyClient_internal(s,!1)}async createClient(s){if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));return this.createClient_internal(s,!1)}}class Q extends O{constructor(s,i){super(s,i),this.searchClientsEndpoint={load:async o=>{let e;try{e=o.url.searchParams.get("userid")?Number(o.url.searchParams.get("userid")):void 0}catch{r.CrossauthLogger.logger.warn(r.j({msg:"Invalid userid "+o.url.searchParams.get("userid")}))}const t=await this.searchClients(o,void 0,void 0,void 0,e);return{...this.baseEndpoint(o),...t}}},this.updateClientEndpoint={load:async o=>{const e=await this.loadClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.updateClient(o)}},this.createClientEndpoint={load:async o=>{const e=await this.emptyClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.createClient(o)}},this.deleteClientEndpoint={load:async o=>{const e=await this.loadDeleteClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.deleteClient(o)}},this.sessionServer=s,u.setParameter("loginUrl",u.ParamType.String,this,i,"LOGIN_URL"),i.clientSearchFn&&(this.clientSearchFn=i.clientSearchFn),this.redirect=i.redirect,this.error=i.error}async searchClients(s,i,o,e,t){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.searchClients_internal(s,i,o,e,t)}async loadClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.loadClient_internal(s)}async updateClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.updateClient_internal(s,!0)}async emptyClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.emptyClient_internal(s,!0)}async createClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.createClient_internal(s,!0)}async loadDeleteClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.loadDeleteClient_internal(s)}async deleteClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.deleteClient_internal(s,!0)}}const L="X-CROSSAUTH-CSRF";function nr(p){let s=[];return p.username==null?s.push("Username must be given"):p.username.length<2?s.push("Username must be at least 2 characters"):p.username.length>254&&s.push("Username must be no longer than 254 characters"),s}function cr(p,s,i,o=["localpassword"]){var a;let t={username:s.username??"",state:"active"};const n=p.locals.user&&C.isAdminFn(p.locals.user);for(let c in s){let l=c.replace(/^user_/,"");if(c.startsWith("user_")&&(n||i.includes(l)))if("type_"+l in s){if(s["type_"+l]=="string")t[l]=s[c];else if(s["type_"+l]=="number"||s["type_"+l]=="integer"||s["type_"+l]=="float")t[l]=Number(s[c]);else if(s["type_"+l]=="boolean"){const h=(a=s[c])==null?void 0:a.toLocaleLowerCase();t[l]=h=="1"||h=="y"||h=="t"||h=="yes"||h=="true"}}else t[l]=s[c]}return t.factor1="localpassword",s.factor1&&o.includes(s.factor1)&&(t.factor1=s.factor1),t.factor2=s.factor2,t}function lr(p,s,i,o){var t;const e=s.locals.user&&C.isAdminFn(s.locals.user);for(let n in i){let a=n.replace(/^user_/,"");if(n.startsWith("user_")&&(e||o.includes(a)))if("type_"+a in i){if(i["type_"+a]=="string")p[a]=i[n];else if(i["type_"+a]=="number"||i["type_"+a]=="integer"||i["type_"+a]=="float")p[a]=Number(i[n]);else if(i["type_"+a]=="boolean"){const c=(t=i[n])==null?void 0:t.toLocaleLowerCase();p[a]=c=="1"||c=="y"||c=="t"||c=="yes"||c=="true"}}else p[a]=i[n]}return p}class N{constructor(s,i,o={}){this.validateUserFn=nr,this.createUserFn=cr,this.updateUserFn=lr,this.allowedFactor2=[],this.allowedFactor2Names=[],this.factor2ProtectedPageEndpoints=[],this.factor2ProtectedApiEndpoints=[],this.loginProtectedPageEndpoints=[],this.loginProtectedApiEndpoints=[],this.loginProtectedExceptionPageEndpoints=[],this.loginProtectedExceptionApiEndpoints=[],this.adminPageEndpoints=[],this.adminApiEndpoints=[],this.adminProtectedExceptionPageEndpoints=[],this.adminProtectedExceptionApiEndpoints=[],this.unauthorizedUrl=void 0,this.enableCsrfProtection=!0,this.enableEmailVerification=!1,this.enablePasswordReset=!1,this.factor2Url="/factor2",this.loginUrl="/login",this.logoutUrl="/logout",this.userAllowedFactor1=["localpassword"],this.adminAllowedFactor1=["localpassword"],this.keyStorage=s,this.userStorage=o.userStorage,this.clientStorage=o.clientStorage,this.authenticators=i,this.sessionManager=new u.SessionManager(s,i,o),this.redirect=o.redirect??m.redirect,this.error=o.error??m.error,u.setParameter("factor2Url",u.ParamType.String,this,o,"FACTOR2_URL"),this.factor2Url.endsWith("/")||(this.factor2Url+="/"),u.setParameter("factor2ProtectedPageEndpoints",u.ParamType.JsonArray,this,o,"FACTOR2_PROTECTED_PAGE_ENDPOINTS"),u.setParameter("factor2ProtectedApiEndpoints",u.ParamType.JsonArray,this,o,"FACTOR2_PROTECTED_API_ENDPOINTS"),u.setParameter("loginProtectedPageEndpoints",u.ParamType.JsonArray,this,o,"LOGIN_PROTECTED_PAGE_ENDPOINTS"),u.setParameter("loginProtectedApiEndpoints",u.ParamType.JsonArray,this,o,"LOGIN_PROTECTED_API_ENDPOINTS"),u.setParameter("loginProtectedExceptionPageEndpoints",u.ParamType.JsonArray,this,o,"LOGIN_PROTECTED_EXCEPTION_PAGE_ENDPOINTS"),u.setParameter("loginProtectedExceptionApiEndpoints",u.ParamType.JsonArray,this,o,"LOGIN_PROTECTED_EXCEPTION_API_ENDPOINTS"),u.setParameter("adminPageEndpoints",u.ParamType.JsonArray,this,o,"ADMIN_PAGE_ENDPOINTS"),u.setParameter("adminApiEndpoints",u.ParamType.JsonArray,this,o,"ADMIN_API_ENDPOINTS"),u.setParameter("adminProtectedExceptionPageEndpoints",u.ParamType.JsonArray,this,o,"ADMIN_PROTECTED_EXCEPTION_PAGE_ENDPOINTS"),u.setParameter("adminProtectedExceptionApiEndpoints",u.ParamType.JsonArray,this,o,"ADMIN_PROTECTED_EXCEPTION_API_ENDPOINTS"),u.setParameter("loginUrl",u.ParamType.JsonArray,this,o,"LOGIN_URL"),u.setParameter("logoutUrl",u.ParamType.JsonArray,this,o,"LOGOUT_URL"),u.setParameter("unauthorizedUrl",u.ParamType.JsonArray,this,o,"UNAUTHORIZED_PAGE"),u.setParameter("userAllowedFactor1",u.ParamType.JsonArray,this,o,"USER_ALLOWED_FACTOR1"),u.setParameter("adminAllowedFactor1",u.ParamType.JsonArray,this,o,"ADMIN_ALLOWED_FACTOR1");let e={};if(u.setParameter("allowedFactor2",u.ParamType.JsonArray,e,o,"ALLOWED_FACTOR2"),this.allowedFactor2Names=o.allowedFactor2??["none"],e.allowedFactor2)for(let t of e.allowedFactor2)t in this.authenticators?this.allowedFactor2.push({name:t,friendlyName:this.authenticators[t].friendlyName,configurable:this.authenticators[t].secretNames().length>0}):t=="none"&&this.allowedFactor2.push({name:"none",friendlyName:"None",configurable:!1});u.setParameter("enableEmailVerification",u.ParamType.Boolean,this,o,"ENABLE_EMAIL_VERIFICATION"),u.setParameter("enablePasswordReset",u.ParamType.Boolean,this,o,"ENABLE_PASSWORD_RESET"),u.setParameter("enableCsrfProtection",u.ParamType.Boolean,this,o,"ENABLE_CSRF_PROTECTION"),u.setParameter("editUserScope",u.ParamType.String,this,o,"EDIT_USER_SCOPE"),o.validateUserFn&&(this.validateUserFn=o.validateUserFn),o.createUserFn&&(this.createUserFn=o.createUserFn),o.updateUserFn&&(this.updateUserFn=o.updateUserFn),o.addToSession&&(this.addToSession=o.addToSession),o.validateSession&&(this.validateSession=o.validateSession),this.userEndpoints=new V(this,o),this.adminEndpoints=new W(this,o),this.userClientEndpoints=new G(this,o),this.adminClientEndpoints=new Q(this,o),this.sessionHook=async({event:t})=>{var d,f;r.CrossauthLogger.logger.debug(r.j({msg:"Session hook"}));let n=[],a;const c=this.sessionManager.csrfCookieName,l=this.sessionManager.sessionCookieName;if(this.enableCsrfProtection){r.CrossauthLogger.logger.debug(r.j({msg:"Getting csrf cookie"}));let g;try{g=this.getCsrfCookieValue(t),g&&this.sessionManager.validateCsrfCookie(g)}catch(E){r.CrossauthLogger.logger.warn(r.j({msg:"Invalid csrf cookie received",cerr:E,hashedCsrfCookie:this.getHashOfCsrfCookie(t)}));try{this.clearCookie(c,this.sessionManager.csrfCookiePath,t)}catch(w){r.CrossauthLogger.logger.debug(r.j({err:w})),r.CrossauthLogger.logger.error(r.j({cerr:w,msg:"Couldn't delete CSRF cookie",ip:t.request.referrer,hashedCsrfCookie:this.getHashOfCsrfCookie(t)}))}g=void 0,t.locals.csrfToken=void 0}if(["GET","OPTIONS","HEAD"].includes(t.request.method))try{if(g){r.CrossauthLogger.logger.debug(r.j({msg:"Valid CSRF cookie - creating token"}));const E=await this.sessionManager.createCsrfFormOrHeaderValue(g);t.locals.csrfToken=E}else{r.CrossauthLogger.logger.debug(r.j({msg:"Invalid CSRF cookie - recreating"}));const{csrfCookie:E,csrfFormOrHeaderValue:w}=await this.sessionManager.createCsrfToken();this.setCsrfCookie(E,t),t.locals.csrfToken=w}this.setHeader(L,t.locals.csrfToken,n)}catch(E){r.CrossauthLogger.logger.error(r.j({msg:"Couldn't create CSRF token",cerr:E,user:(d=t.locals.user)==null?void 0:d.username,hashedSessionCookie:this.getHashOfSessionCookie(t)})),r.CrossauthLogger.logger.debug(r.j({err:E})),this.clearCookie(c,this.sessionManager.csrfCookiePath,t),t.locals.csrfToken=void 0}else if(g)try{await this.csrfToken(t,n)}catch(E){r.CrossauthLogger.logger.error(r.j({msg:"Couldn't create CSRF token",cerr:E,user:(f=t.locals.user)==null?void 0:f.username,hashedSessionCookie:this.getHashOfSessionCookie(t)})),r.CrossauthLogger.logger.debug(r.j({err:E}))}}t.locals.user=void 0,t.locals.authType=void 0;const h=this.getSessionCookieValue(t);if(r.CrossauthLogger.logger.debug(r.j({msg:"Getting session cookie"})),h)try{const g=this.sessionManager.getSessionId(h);let{key:E,user:w}=await this.sessionManager.userForSessionId(g);this.validateSession&&this.validateSession(E,w,t);const k=t.url.pathname;if(r.CrossauthLogger.logger.debug(r.j({msg:"Session cookie is for user "+w})),w&&this.allowedFactor2.length>0&&(w.state==r.UserState.factor2ResetNeeded||!this.allowedFactor2Names.includes(w.factor2?w.factor2:"none"))){if(!this.userEndpoints.configureFactor2Url)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set configureFactor2Url in session server");if(!this.userEndpoints.changeFactor2Url)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set changeFactor2Url in session server");if(!this.logoutUrl)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set logoutUrl in session server");[this.userEndpoints.changeFactor2Url,this.userEndpoints.configureFactor2Url,this.loginUrl,this.logoutUrl].includes(k)||(a=302,n.push({name:"location",value:this.userEndpoints.changeFactor2Url+"?required=true&next="+encodeURIComponent("login?next="+t.url)}))}t.locals.sessionId=g,t.locals.user=w,t.locals.authType="cookie",r.CrossauthLogger.logger.debug(r.j({msg:"Valid session id",user:w==null?void 0:w.username}))}catch{r.CrossauthLogger.logger.warn(r.j({msg:"Invalid session cookie received",hashedSessionCookie:this.getHashOfSessionCookie(t)})),this.clearCookie(l,this.sessionManager.sessionCookiePath,t)}return{headers:n,status:a}},this.twoFAHook=async({event:t})=>{var h;if(r.CrossauthLogger.logger.debug(r.j({msg:"twoFAHook",username:(h=t.locals.user)==null?void 0:h.username})),!this.userStorage)throw this.error(500,"No user storage defined");const n=this.getSessionCookieValue(t),a=this.isFactor2PageProtected(t),c=this.isFactor2ApiProtected(t);let l;if(n)if(t.locals.user)l=t.locals.user;else{const d=await this.getSessionData(t,"user");if(d){const f=await this.userStorage.getUserByUsername(d.username,{skipActiveCheck:!0});(f.user.status==r.UserState.active||f.user.state==r.UserState.factor2ResetNeeded)&&(l=f.user)}}if(l&&n&&l.factor2!=""&&(a||c))if(r.CrossauthLogger.logger.debug(r.j({msg:"Factor2-protected endpoint visited"})),["GET","OPTIONS","HEAD"].includes(t.request.method)){r.CrossauthLogger.logger.debug(r.j({msg:"Factor2-protected GET endpoint - cancelling 2FA"}));const d=this.getSessionCookieValue(t);if(d){const f=this.sessionManager.getSessionId(d);if("pre2fa"in await this.sessionManager.dataForSessionId(f)){r.CrossauthLogger.logger.debug(r.j({msg:"Cancelling 2FA"}));try{await this.sessionManager.cancelTwoFactorPageVisit(d)}catch(E){r.CrossauthLogger.logger.debug(r.j({err:E})),r.CrossauthLogger.logger.error(r.j({msg:"Failed cancelling 2FA",cerr:E,user:l.username,hashedSessionCookie:this.getHashOfSessionCookie(t)}))}}}}else{const d=this.sessionManager.getSessionId(n),f=await this.sessionManager.dataForSessionId(d);if("pre2fa"in f){r.CrossauthLogger.logger.debug(r.j({msg:"Completing 2FA"}));const g=this.authenticators[f.pre2fa.factor2],E=[...g.secretNames(),...g.transientSecretNames()];let w={};const k=new S;await k.loadData(t);for(let v of k.keys())E.includes(v)&&(w[v]=k.get(v)??"");const y=this.getSessionCookieValue(t);if(!y)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session cookie found");let _;try{await this.sessionManager.completeTwoFactorPageVisit(w,t.locals.sessionId??"")}catch(v){_=r.CrossauthError.asCrossauthError(v),r.CrossauthLogger.logger.debug(r.j({err:v}));const A=r.CrossauthError.asCrossauthError(v);r.CrossauthLogger.logger.error(r.j({msg:_.message,cerr:v,user:k.get("username"),errorCode:A.code,errorCodeName:A.codeName}))}if(_)if(_.code==r.ErrorCode.Expired){r.CrossauthLogger.logger.debug(r.j({msg:"Error - cancelling 2FA"}));try{await this.sessionManager.cancelTwoFactorPageVisit(y)}catch(v){r.CrossauthLogger.logger.error(r.j({msg:"Failed cancelling 2FA",cerr:v,user:l.username,hashedSessionCookie:this.getHashOfSessionCookie(t)})),r.CrossauthLogger.logger.debug(r.j({err:v}))}return this.error(401,{message:"Sorry, your code has expired"}),{ok:!1,twofa:!0}}else return a?{twofa:!0,ok:!1,response:new Response("",{status:302,statusText:r.httpStatus(302),headers:{Location:this.factor2Url+"?error="+r.ErrorCode[_.code]}})}:{twofa:!0,ok:!1,response:new Response(JSON.stringify({ok:!1,errorMessage:_.message,errorMessages:_.messages,errorCode:_.code,errorCodeName:r.ErrorCode[_.code]}),{status:_.httpStatus,statusText:r.httpStatus(_.httpStatus),headers:{"content-tyoe":"application/json"}})};return N.updateRequest(t,f.pre2fa.body,f.pre2fa["content-type"]),{twofa:!0,ok:!0}}else{if(r.CrossauthLogger.logger.debug(r.j({msg:"Starting 2FA",username:l.username})),this.enableCsrfProtection&&!t.locals.csrfToken){const w=new r.CrossauthError(r.ErrorCode.Forbidden,"CSRF token missing");return{twofa:!0,ok:!1,response:new Response(JSON.stringify({ok:!1,errorMessage:w.message,errorMessages:w.messages,errorCode:w.code,errorCodeName:r.ErrorCode[w.code]}),{status:w.httpStatus,statusText:r.httpStatus(w.httpStatus),headers:{"content-tyoe":"application/json"}})}}const g=new S;await g.loadData(t);let E=t.request.headers.get("content-type");return await this.sessionManager.initiateTwoFactorPageVisit(l,t.locals.sessionId??"",g.toObject(),t.request.url.replace(/\?.*$/,""),E||void 0),a?{twofa:!0,ok:!0,response:new Response("",{status:302,statusText:r.httpStatus(302),headers:{Location:this.factor2Url}})}:{twofa:!0,ok:!0,response:new Response(JSON.stringify({ok:!0,factor2Required:!0}),{headers:{"content-tyoe":"application/json"}})}}}return{twofa:!1,ok:!0}}}getSessionCookieValue(s){if(s.cookies&&s.cookies.get(this.sessionManager.sessionCookieName))return s.cookies.get(this.sessionManager.sessionCookieName)}getCsrfCookieValue(s){if(s.cookies&&s.cookies.get(this.sessionManager.csrfCookieName))return s.cookies.get(this.sessionManager.csrfCookieName)}clearCookie(s,i,o){o.cookies.delete(s,{path:i})}setHeaders(s,i){for(let o of s)i.headers.append(o.name,o.value)}setCsrfCookie(s,i){i.cookies.set(s.name,s.value,u.toCookieSerializeOptions(s.options))}setHeader(s,i,o){o.push({name:s,value:i})}getHashOfSessionCookie(s){const i=this.getSessionCookieValue(s);if(!i)return"";try{return u.Crypto.hash(i)}catch{}return""}getHashOfCsrfCookie(s){const i=this.getCsrfCookieValue(s);if(!i)return"";try{return u.Crypto.hash(i)}catch{}return""}async csrfToken(s,i){var e,t,n;let o;if(s.request.headers&&s.request.headers.has(L.toLowerCase())){const a=s.request.headers.get(L.toLowerCase());Array.isArray(a)?o=a[0]:a&&(o=a)}if(!o){if(!((e=s.request)!=null&&e.body)){r.CrossauthLogger.logger.warn(r.j({msg:"Received CSRF header but not token",ip:s.request.referrerPolicy,hashedCsrfCookie:this.getHashOfCsrfCookie(s)}));return}const a=s.request.headers.get("content-type");if(a=="application/json")o=(await((n=(t=s.request)==null?void 0:t.clone())==null?void 0:n.json())).csrfToken;else if(a=="application/x-www-form-urlencoded"||a=="multipart/form-data"){const l=(await s.request.clone().formData()).get("csrfToken");l&&typeof l=="string"&&(o=l)}}if(o)try{this.sessionManager.validateDoubleSubmitCsrfToken(this.getCsrfCookieValue(s),o),s.locals.csrfToken=o,this.setHeader(L,o,i)}catch{r.CrossauthLogger.logger.warn(r.j({msg:"Invalid CSRF token",hashedCsrfCookie:this.getHashOfCsrfCookie(s)})),this.clearCookie(this.sessionManager.csrfCookieName,this.sessionManager.csrfCookiePath,s),s.locals.csrfToken=void 0}else s.locals.csrfToken=void 0;return o}static updateRequest(s,i,o){let e;if(o=="application/json")e=JSON.stringify(i);else{e="";for(let t in i){const n=i[t];e.length>0&&(e+="&"),e+=encodeURIComponent(t)+"="+encodeURIComponent(n)}}return s.request=new Request(s.request.url,{method:"POST",headers:s.request.headers,body:e}),s}getHashOfSessionId(s){if(!s.locals.sessionId)return"";try{return u.Crypto.hash(s.locals.sessionId)}catch{}return""}async factor2PageVisitStarted(s){try{return this.getSessionData(s,"pre2fa")!=null}catch(i){const o=r.CrossauthError.asCrossauthError(i);return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o,msg:"Couldn't get pre2fa data from session"})),!1}}isLoginPageProtected(s){const i=new URL(typeof s=="string"?s:s.request.url);if(i.pathname==this.loginUrl)return!1;let o=!1;return o=this.loginProtectedExceptionPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o?!1:this.loginProtectedPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),!1)}isLoginApiProtected(s){const i=new URL(typeof s=="string"?s:s.request.url);if(i.pathname==this.loginUrl)return!1;let o=!1;return o=this.loginProtectedExceptionApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o?!1:this.loginProtectedApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),!1)}isFactor2PageProtected(s){const i=new URL(typeof s=="string"?s:s.request.url);return this.factor2ProtectedPageEndpoints.reduce((e,t)=>e||T.minimatch(i.pathname,t),!1)}isFactor2ApiProtected(s){const i=new URL(typeof s=="string"?s:s.request.url);return this.factor2ProtectedApiEndpoints.reduce((e,t)=>e||T.minimatch(i.pathname,t),!1)}isAdminPageEndpoint(s){const i=new URL(typeof s=="string"?s:s.request.url);let o=!1;return o=this.adminProtectedExceptionPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o||(o=this.loginProtectedExceptionPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o)?!1:this.adminPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),!1)}isAdminApiEndpoint(s){const i=new URL(typeof s=="string"?s:s.request.url);let o=!1;return o=this.adminProtectedExceptionApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o||(o=this.loginProtectedExceptionApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o)?!1:this.adminApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),!1)}async createAnonymousSession(s,i){r.CrossauthLogger.logger.debug(r.j({msg:"Creating anonympous session ID "}));const o=new S;await o.loadData(s);let e=this.addToSession?this.addToSession(s,o.toObject()):{};i&&(e.data=JSON.stringify(i));let{sessionCookie:t,csrfCookie:n,csrfFormOrHeaderValue:a}=await this.sessionManager.createAnonymousSession(e);s.cookies.set(t.name,t.value,u.toCookieSerializeOptions(t.options)),this.enableCsrfProtection&&(s.locals.csrfToken=a,s.cookies.set(n.name,n.value,u.toCookieSerializeOptions(n.options))),s.locals.user=void 0;const c=this.sessionManager.getSessionId(t.value);return s.locals.sessionId=c,t.value}async refreshLocals(s){try{const i=this.getSessionCookieValue(s);if(i){const o=this.sessionManager.getSessionId(i);s.locals.sessionId=o;const e=await this.sessionManager.userForSessionId(o);s.locals.user=e.user}else s.locals.sessionId=void 0,s.locals.user=void 0}catch(i){r.CrossauthLogger.logger.error(r.j({errr:i}))}}csrfProtectionEnabled(){return this.enableCsrfProtection}getCsrfToken(s){return s.locals.csrfToken}getUser(s){return s.locals.user}async getSessionData(s,i){try{const o=s.locals.sessionId?await this.sessionManager.dataForSessionId(s.locals.sessionId):void 0;if(o&&i in o)return o[i]}catch(o){r.CrossauthLogger.logger.error(r.j({msg:"Couldn't get "+i+"from session",cerr:o})),r.CrossauthLogger.logger.debug(r.j({err:o}))}}async updateSessionData(s,i,o){if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session present");await this.sessionManager.updateSessionData(s.locals.sessionId,i,o)}async updateManySessionData(s,i){if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session present");await this.sessionManager.updateManySessionData(s.locals.sessionId,i)}async deleteSessionData(s,i){s.locals.sessionId?await this.sessionManager.deleteSessionData(s.locals.sessionId,i):r.CrossauthLogger.logger.debug(r.j({msg:`Attempting to delete session data ${i} when no session is present`}))}}exports.JsonOrFormData=S;exports.SvelteKitAdminClientEndpoints=Q;exports.SvelteKitAdminEndpoints=W;exports.SvelteKitApiKeyServer=x;exports.SvelteKitAuthorizationServer=B;exports.SvelteKitOAuthClient=j;exports.SvelteKitOAuthResourceServer=H;exports.SvelteKitServer=C;exports.SvelteKitSessionAdapter=tr;exports.SvelteKitSessionServer=N;exports.SvelteKitSharedClientEndpoints=O;exports.SvelteKitUserClientEndpoints=G;exports.SvelteKitUserEndpoints=V;exports.defaultClientSearchFn=J;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("minimatch"),u=require("@crossauth/backend"),r=require("@crossauth/common"),m=require("@sveltejs/kit");require("cookie");const P=require("jwt-decode"),$=require("qrcode");class z{constructor(s){this.values=[],this.keys=[],this.i=0;for(let i in s)this.keys.push(i),this.values.push(s[i])}next(){if(this.i==this.values.length)return{done:!0,value:["",""]};const s=[this.keys[this.i],this.values[this.i]];return this.i++,{done:!1,value:s[0]}}[Symbol.iterator](){return this}}class S{constructor(s=!0){this.clone=s}async loadData(s){var o,e,t,n;if(!((o=s.request)!=null&&o.body))return;const i=s.request.headers.get("content-type");i=="application/json"?this.jsonData=this.clone?await((t=(e=s.request)==null?void 0:e.clone())==null?void 0:t.json()):await((n=s.request)==null?void 0:n.json()):(i=="application/x-www-form-urlencoded"||i!=null&&i.startsWith("multipart/form-data"))&&(this.formData=this.clone?await s.request.clone().formData():await s.request.formData())}get(s){if(this.jsonData)return this.jsonData[s];if(this.formData){const i=this.formData.get(s);if(i&&typeof i=="string")return i}}getAsString(s){return this.get(s)}getAsBoolean(s){const i=this.get(s);if(i==null)return;const o=i.toLowerCase();return o=="t"||o=="true"||o=="1"||o=="y"||o=="yes"||o=="on"}getAsNumber(s){const i=this.get(s);if(i!=null)try{return Number(i)}catch{throw new r.CrossauthError(r.ErrorCode.FormEntry,"Value for "+s+" is not a number")}}has(s){return(this.jsonData&&s in this.jsonData||this.formData&&this.formData.has(s))??!1}keys(){return this.jsonData?new z(this.jsonData):this.formData?this.formData.keys():new z({})}toObject(){var s;if(this.jsonData)return this.jsonData;if(this.formData){let i={};for(let o of this.formData.entries())i[o[0]]=((s=o[1])==null?void 0:s.toString())??"";return i}return{}}}class x{constructor(s,i,o={}){this.userStorage=s,this.apiKeyManager=new u.ApiKeyManager(i,o),this.hook=async({event:e})=>{r.CrossauthLogger.logger.debug("APIKey hook");const t=e.request.headers.get("authorization");if(t)try{r.CrossauthLogger.logger.debug(r.j({msg:"Received authorization header"}));const n=await this.apiKeyManager.validateToken(t);r.CrossauthLogger.logger.debug(r.j({msg:"Valid API key",hahedApiKey:u.ApiKeyManager.hashSignedApiKeyValue(n.value)}));const a=u.KeyStorage.decodeData(n.data);if(e.locals.apiKey={...n,...a},"scope"in a&&Array.isArray(a.scope)){let c=[];for(let l of a.scope)typeof l=="string"&&c.push(l);e.locals.scope=c}if(n.userid)try{const{user:c}=await this.userStorage.getUserById(n.userid);e.locals.user=c,e.locals.authType="apiKey",r.CrossauthLogger.logger.debug(r.j({msg:"API key is for user",userid:c.id,user:c.username,hahedApiKey:u.ApiKeyManager.hashSignedApiKeyValue(n.value)}))}catch(c){r.CrossauthLogger.logger.error(r.j({msg:"API key has invalid user",userid:n.userid,hashedApiKey:u.ApiKeyManager.hashSignedApiKeyValue(n.value)})),r.CrossauthLogger.logger.debug(r.j({err:c}))}}catch(n){r.CrossauthLogger.logger.error(r.j({msg:"Invalid authorization header received",header:t})),r.CrossauthLogger.logger.debug(r.j({err:n}))}}}}const K="upstreamoauth";class B{constructor(s,i,o,e,t={}){var n;this.loginUrl="/login",this.refreshTokenType="json",this.refreshTokenCookieName="CROSSAUTH_REFRESH_TOKEN",this.refreshTokenCookieDomain=void 0,this.refreshTokenCookieHttpOnly=!1,this.refreshTokenCookiePath="/",this.refreshTokenCookieSecure=!0,this.refreshTokenCookieSameSite="strict",this.authorizeEndpointUrl="/oauth/authorize",this.tokenEndpointUrl="/oauth/token",this.jwksEndpointUrl="/oauth/jwks",this.oidcConfigurationEndpoint={get:async a=>m.json(this.authServer.oidcConfiguration({authorizeEndpoint:this.authorizeEndpointUrl,tokenEndpoint:this.tokenEndpointUrl,jwksUri:this.jwksEndpointUrl,additionalClaims:[]}))},this.jwksGetEndpoint={get:async a=>{try{return m.json(this.authServer.jwks())}catch(c){const l=r.CrossauthError.asCrossauthError(c);return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),m.json({error:l.oauthErrorCode,error_description:l.message})}}},this.getCsrfTokenEndpoint={get:async a=>{var l;if(!this.csrfTokens)return m.json({ok:!1,error:"invalid_request",error_description:"No CSRF token"});let c="";try{const{csrfCookie:h,csrfFormOrHeaderValue:d}=await this.createCsrfToken();return c=h.value,a.cookies.set(h.name,h.value,u.toCookieSerializeOptions(h.options)),m.json({ok:!0,csrfToken:d})}catch(h){const d=r.CrossauthError.asCrossauthError(h);return r.CrossauthLogger.logger.error(r.j({msg:"getcsrftoken failure",user:(l=a.locals.user)==null?void 0:l.username,hashedCsrfCookie:u.Crypto.hash(c.split(".")[0]),error:d.code,errorCodeName:d.codeName})),r.CrossauthLogger.logger.debug(r.j({err:h})),r.CrossauthLogger.logger.error({cerr:h}),m.json({ok:!1,error:d.oauthErrorCode,error_description:d.message})}}},this.authorizeEndpoint={load:async a=>{var g,E;if(!(this.authServer.validFlows.includes(r.OAuthFlows.AuthorizationCode)||this.authServer.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)||this.authServer.validFlows.includes(r.OAuthFlows.OidcAuthorizationCode)))throw this.error(401,"authorize cannot be called because the authorization code flows are not supported");if(this.authServer.upstreamClient&&this.authServer.upstreamClientOptions){const w=u.Crypto.randomValue(32);let k=this.getAuthorizeQuery(a);if(!k.query)return k.error;let y=k.query;if(y.response_type=="code"){let _;try{_=await this.clientStorage.getClientById(y.client_id)}catch(F){return r.CrossauthLogger.logger.debug(r.j({err:F})),{ok:!1,error:"unauthorized_client",error_description:"Client is not authorized"}}let v;y.scope&&(v=decodeURIComponent(y.scope).split(" ")),v=v==null?void 0:v.filter(F=>F.length>0);const A=await this.authServer.upstreamClient.startAuthorizationCodeFlow(w,y.scope,y.code_challenge,y.code_challenge!=null);if(A.error)return{ok:!1,error:A.error,error_description:A.error_description};{const F=await this.authServer.getAuthorizationCode(_,y.redirect_uri,v,w,y.code_challenge,y.code_challenge_method);if(!F.code)return{ok:!1,error:"server_error",error_description:"Couldn't create authorization code"};const Y={scope:y.scope,state:w,code:F.code,orig_client_id:y.client_id,orig_redirect_uri:y.redirect_uri,orig_state:y.state};if(!this.authServer.upstreamClientOptions.options.redirect_uri)return{ok:!1,error:"server_error",error_description:"redirect uri not given for upstream client"};const X=this.authServer.upstreamClientOptions.sessionDataName??K;await this.storeSessionData(a,Y,X);let D=A.url;throw r.CrossauthLogger.logger.debug(r.j({msg:"upstream url "+D})),this.redirect(302,D)}}else return{ok:!1,error:"invalid_request",error_description:"authorize can only be called with response_type code"}}if(!a.locals.user)return this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(a.request.url));let c=this.getAuthorizeQuery(a);if(!c.query)return c.error;let l=c.query;r.CrossauthLogger.logger.debug(r.j({msg:"validating authorize parameters"}));let{error_description:h}=this.authServer.validateAuthorizeParameters(l),d;if(h?(d=new r.CrossauthError(r.ErrorCode.BadRequest,h),r.CrossauthLogger.logger.error(r.j({msg:"authorize parameter invalid",cerr:d,user:(g=a.locals.user)==null?void 0:g.username}))):r.CrossauthLogger.logger.error(r.j({msg:"authorize parameter valid",user:(E=a.locals.user)==null?void 0:E.username})),d)return{ok:!1,error:d.oauthErrorCode,error_description:d.message};let f=!1;if(r.CrossauthLogger.logger.debug(r.j({msg:"Checking scopes have been authorized",scope:l.scope})),l.scope?f=await this.authServer.hasAllScopes(l.client_id,a.locals.user,l.scope.split(" ")):f=await this.authServer.hasAllScopes(l.client_id,a.locals.user,[null]),f){r.CrossauthLogger.logger.debug(r.j({msg:"All scopes authorized",scope:l.scope}));const w=await this.authorize(a,!0,{responseType:l.response_type,client_id:l.client_id,redirect_uri:l.redirect_uri,scope:l.scope,state:l.state,codeChallenge:l.code_challenge,codeChallengeMethod:l.code_challenge_method});return{ok:!1,error:w.error??"server_error",error_description:w.error_description??"An unexpected error occurred"}}else{r.CrossauthLogger.logger.debug(r.j({msg:"Not all scopes authorized",scope:l.scope}));try{const w=await this.clientStorage.getClientById(l.client_id);return{ok:!0,authorizationNeeded:{user:a.locals.user,response_type:l.response_type,client_id:l.client_id,client_name:w.client_name,redirect_uri:l.redirect_uri,scope:l.scope,scopes:l.scope?l.scope.split(" "):void 0,state:l.state,code_challenge:l.code_challenge,code_challenge_method:l.code_challenge_method,csrfToken:a.locals.csrfToken},...this.baseEndpoint}}catch(w){const k=w;return r.CrossauthLogger.logger.debug(r.j({err:k})),{ok:!1,error:"unauthorized_client",error_description:"Not a valid client"}}}},actions:{default:async a=>{var h;let c;try{var l=new S;await l.loadData(a),c=l.toObject();const d=l.getAsBoolean("authorized"),f=c.response_type,g=c.client_id,E=c.redirect_uri,w=c.scope,k=c.state,y=c.code_challenge,_=c.code_challenge_method;let v;if(d==null&&(v="authorized"),f?g?E?k||(v="state"):v="redirect_uri":v="client_id":v="response_type",v)return{ok:!1,error:"invalid_request",error_description:"Invalid form: does not contain "+v+" parameter"};if(!a.locals.user)return this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(a.request.url));if((h=this.svelteKitServer.sessionServer)!=null&&h.enableCsrfProtection&&!a.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const A=await this.authorize(a,d??!1,{responseType:f,client_id:g,redirect_uri:E,scope:w,state:k,codeChallenge:y,codeChallengeMethod:_});return{ok:!1,error:A.error??"server_error",error_description:A.error_description??"An unexpected error occurred"}}catch(d){if(C.isSvelteKitError(d)||C.isSvelteKitRedirect(d))throw d;let f=r.CrossauthError.asCrossauthError(d,"Couldn't process authorization code");return{error:f.oauthErrorCode,error_description:f.message,ok:!1,formData:c}}}}},this.tokenEndpoint={post:async a=>{let c;try{if(!(this.authServer.validFlows.includes(r.OAuthFlows.AuthorizationCode)||this.authServer.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)||this.authServer.validFlows.includes(r.OAuthFlows.OidcAuthorizationCode)||this.authServer.validFlows.includes(r.OAuthFlows.ClientCredentials)||this.authServer.validFlows.includes(r.OAuthFlows.RefreshToken)||this.authServer.validFlows.includes(r.OAuthFlows.Password)||this.authServer.validFlows.includes(r.OAuthFlows.PasswordMfa||this.authServer.validFlows.includes(r.OAuthFlows.DeviceCode))))return m.json({ok:!1,error:"invalid_request",error_description:"Token endpoint cannot be called as the supported OAuth flow types don't require it"},{status:500});var l=new S;await l.loadData(a),c=l.toObject();const{client_id:h,client_secret:d}=this.getClientIdAndSecret(c,a);if(c.grant_type=="authorization_code"&&this.authServer.upstreamClient&&this.authServer.upstreamClientOptions){const w=await this.authServer.getAuthorizationCodeData(c.code);return w==null?m.json({error:"access_denied",error_description:"Invalid or expired authorization code"}):w.access_token?(await this.authServer.deleteAuthorizationCodeData(c.code),m.json({access_token:w.access_token,id_token:w.id_token,id_payload:w.id_payload,refresh_token:w.refresh_token,expires_in:w.expires_in})):m.json({error:"access_denied",error_description:"No access token was issued"},{status:401})}let f=c.refresh_token,g=a.cookies.get(this.refreshTokenCookieName);if((this.refreshTokenType=="cookie"&&g||this.refreshTokenType=="both"&&g&&f==null)&&this.csrfTokens){const w=a.cookies.get(this.csrfTokens.cookieName);let k=a.request.headers.get(this.csrfTokens.headerName.toLowerCase());if(Array.isArray(k)&&(k=k[0]),!w||!k)return m.json({ok:!1,error:"access_denied",error_description:"Invalid csrf token"},{status:401});try{this.csrfTokens.validateDoubleSubmitCsrfToken(w,k)}catch(y){return r.CrossauthLogger.logger.debug(r.j({err:y})),r.CrossauthLogger.logger.warn(r.j({cerr:y,msg:"Invalid csrf token",client_id:c.client_id})),m.json({ok:!1,error:"access_denied",error_description:"Invalid csrf token"},{status:401})}f=g}const E=await this.authServer.tokenEndpoint({grantType:c.grant_type,client_id:h,client_secret:d,scope:c.scope,codeVerifier:c.code_verifier,code:c.code,username:c.username,password:c.password,mfaToken:c.mfa_token,oobCode:c.oob_code,bindingCode:c.binding_code,otp:c.otp,refreshToken:f,deviceCode:c.device_code});if(E.refresh_token&&this.refreshTokenType!="json"&&this.setRefreshTokenCookie(a,E.refresh_token,E.expires_in),E.error=="authorization_pending")return m.json(E);if(E.error||!E.access_token){let w="server_error",k="Neither code nor error received when requestoing authorization";E.error&&(w=E.error),E.error_description&&(k=E.error_description);const y=r.CrossauthError.fromOAuthError(w,k);return r.CrossauthLogger.logger.error(r.j({cerr:y})),m.json(E,{status:y.httpStatus})}return m.json(E)}catch(h){const d=r.CrossauthError.asCrossauthError(h);return r.CrossauthLogger.logger.debug({err:h}),r.CrossauthLogger.logger.error({cerr:h}),m.json({error:d.oauthErrorCode,error_description:d.message},{status:d.httpStatus})}}},this.upstreamRedirectUriEndpoint={get:async a=>{var l;let c={};try{if(!this.authServer.upstreamClientOptions)return r.CrossauthLogger.logger.error(r.j({msg:"Cannot call upstreamRedirectUriEndpoint if upstreamClient not defined"})),m.json({ok:!1,error:"server_error",error_description:"Cannot call upstreamRedirectUriEndpoint if upstreamClient not defined"});if(r.CrossauthLogger.logger.debug(r.j({msg:"upstreamRedirectUriEndpoint"})),!this.authServer.upstreamClient||!this.authServer.upstreamClientOptions.tokenMergeFn)return r.CrossauthLogger.logger.error(r.j({msg:"upstreamRedirectUri endpoint called but no upstreamClient or merge function set"})),this.redirectError(c.orig_redirect_uri,"server_error","upstreamRedirectUri endpoint called but no upstreamClient or merge function set");const h=a.url.searchParams.get("code")??"",d=a.url.searchParams.get("state")??void 0,f=a.url.searchParams.get("error")??void 0,g=a.url.searchParams.get("error")??void 0,E=this.authServer.upstreamClientOptions.sessionDataName??K;if(c=await((l=this.svelteKitServer.sessionAdapter)==null?void 0:l.getSessionData(a,E))??{},(c==null?void 0:c.state)!=d)throw r.CrossauthLogger.logger.error(r.j({msg:"State does not match"})),new r.CrossauthError(r.ErrorCode.Unauthorized,"State does not match");const w=await this.authServer.upstreamClient.redirectEndpoint(h,c==null?void 0:c.scope,c==null?void 0:c.codeVerifier,f,g);if(w.error)return r.CrossauthLogger.logger.error(r.j({msg:w.error_description})),this.redirectError(c.orig_redirect_uri,w.error,w.error_description??"unknown error");let k=w.access_token;if(w.access_token&&this.authServer.upstreamClientOptions.accessTokenIsJwt){const _=await this.authServer.upstreamClient.getAccessPayload(w.access_token,!1);if(_.error)return m.json(_);if(_.payload)k=_.payload;else return r.CrossauthLogger.logger.error(r.j({msg:"No error or access payload received when querying access token"})),this.redirectError(c.orig_redirect_uri,"server_error","No error or access payload received when querying access token")}const y=await this.authServer.upstreamClientOptions.tokenMergeFn(k??"",w.id_payload,this.authServer.userStorage);if(y.authorized){const _=await this.authServer.createTokensFromPayload(c.orig_client_id,y.access_payload,y.id_payload);c={...c,access_token:_.access_token,id_token:_.id_token,id_payload:_.id_payload,expires_in:_.expires_in,refresh_token:w.refresh_token};let v=await this.authServer.getAuthorizationCodeData(c.code);throw v={...v,access_token:_.access_token,id_token:_.id_token,id_payload:_.id_token,refresh_token:w.refresh_token,expires_in:_.expires_in},await this.authServer.setAuthorizationCodeData(c.code,v),this.redirect(302,this.authServer.redirect_uri(c.orig_redirect_uri,c.code,c.orig_state))}else return r.CrossauthLogger.logger.error(r.j({msg:y.error_description??"Error merging tokens"})),this.redirectError(c.orig_redirect_uri,y.error??"server_error",y.error_description??"Error merging tokens")}catch(h){if(C.isSvelteKitRedirect(h)||C.isSvelteKitError(h))throw h;const d=r.CrossauthError.asCrossauthError(h);return r.CrossauthLogger.logger.debug({err:h}),r.CrossauthLogger.logger.error({cerr:h}),this.redirectError(c.orig_redirect_uri,d.oauthErrorCode,d.message)}}},this.mfaAuthenticatorsEndpoint={get:async a=>{try{var c=new S;return await c.loadData(a),m.json(await this.mfaAuthenticators(a))}catch(l){const h=r.CrossauthError.asCrossauthError(l);return r.CrossauthLogger.logger.debug({err:l}),r.CrossauthLogger.logger.error({cerr:l}),m.json({error:h.oauthErrorCode,error_description:h.message})}},post:async a=>{try{var c=new S;await c.loadData(a);let l=await this.mfaAuthenticators(a),h=200;return!Array.isArray(l)&&l.error=="access_denied"?h=401:!Array.isArray(l)&&l.error&&(h=500),m.json(l,{status:h})}catch(l){const h=r.CrossauthError.asCrossauthError(l);return r.CrossauthLogger.logger.debug({err:l}),r.CrossauthLogger.logger.error({cerr:l}),m.json({error:h.oauthErrorCode,error_description:h.message},{status:h.httpStatus})}}},this.mfaChallengeEndpoint={post:async a=>{try{var c=new S;await c.loadData(a);const l=await this.mfaChallenge(a);let h=200;return l.error=="access_denied"?h=401:l.error&&(h=500),m.json(l,{status:h})}catch(l){const h=r.CrossauthError.asCrossauthError(l);return r.CrossauthLogger.logger.debug({err:l}),r.CrossauthLogger.logger.error({cerr:l}),m.json({error:h.oauthErrorCode,error_description:h.message},{status:500})}}},this.deviceAuthorizationEndpoint={post:async a=>{let c;try{if(!this.authServer.validFlows.includes(r.OAuthFlows.DeviceCode))return m.json({ok:!1,error:"invalid_request",error_description:"Device authorization endpoint cannot be called as the supported OAuth flow types don't require it"});var l=new S;await l.loadData(a),c=l.toObject();const{client_id:h,client_secret:d}=this.getClientIdAndSecret(c,a),f=await this.authServer.deviceAuthorizationEndpoint({client_id:h,client_secret:d,scope:c.scope});if(f.error){const g=r.CrossauthError.fromOAuthError(f.error,f.error_description);return r.CrossauthLogger.logger.error(r.j({cerr:g})),m.json(f,{status:500})}if(!f.device_code||!f.user_code||!f.verification_uri||!f.verification_uri_complete||!f.expires_in){let g="server_error",E="Device authorization result has missing data";const w=new r.CrossauthError(r.ErrorCode.UnknownError,E);return r.CrossauthLogger.logger.error(r.j({cerr:w})),m.json({error:g,error_description:E},{status:500})}return m.json(f)}catch(h){const d=r.CrossauthError.asCrossauthError(h);return r.CrossauthLogger.logger.debug({err:h}),r.CrossauthLogger.logger.error({cerr:h}),m.json({error:d.oauthErrorCode,error_description:d.message},{status:500})}}},this.deviceEndpoint={load:async a=>{if(!this.authServer.validFlows.includes(r.OAuthFlows.DeviceCode))throw this.error(401,"device cannot be called because the device code flow is not supported");if(!a.locals.user)return this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(a.request.url));let c=a.url.searchParams.get("user_code");return c?await this.applyUserCode(c,a,a.locals.user):{ok:!0,completed:!1,retryAllowed:!0,user:a.locals.user,csrfToken:a.locals.csrfToken}},actions:{userCode:async a=>{if(!a.locals.user)throw this.error(401,"Access Denied");try{var c=new S;await c.loadData(a);const l=c.get("user_code");return l?await this.applyUserCode(l,a,a.locals.user):{ok:!1,completed:!1,retryAllowed:!0,error:"access_denied",error_description:"No user code given"}}catch(l){if(C.isSvelteKitError(l)||C.isSvelteKitRedirect(l))throw l;let h=r.CrossauthError.asCrossauthError(l,"Couldn't validate user code");return{ok:!1,completed:!1,retryAllowed:!0,error:h.oauthErrorCode,error_description:h.message}}},authorize:async a=>{var h;let c;try{var l=new S;await l.loadData(a),c=l.toObject();const d=l.getAsBoolean("authorized"),f=c.scope,g=c.client_id,E=c.user_code;let w;if(d==null&&(w="authorized"),g==null&&(w="client_id"),E==null&&(w="user_code"),w)return{ok:!1,completed:!1,retryAllowed:!1,error:"invalid_request",error_description:"Invalid form: does not contain "+w+" parameter"};if(!a.locals.user)return this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(a.request.url));if((h=this.svelteKitServer.sessionServer)!=null&&h.enableCsrfProtection&&!a.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);return(await this.authServer.validateAndPersistScope(g,f,a.locals.user)).error?{ok:!1,completed:!1,retryAllowed:!1,error:"unauthorized_client",error_description:"You did not authorize access to your account"}:await this.applyUserCode(E,a,a.locals.user)}catch(d){if(C.isSvelteKitError(d)||C.isSvelteKitRedirect(d))throw d;let f=r.CrossauthError.asCrossauthError(d,"Couldn't process authorization code");return{error:f.oauthErrorCode,error_description:f.message,ok:!1,completed:!1,retryAllowed:!1}}}}},this.svelteKitServer=s,this.clientStorage=i,t.redirect&&(this.redirect=t.redirect),t.error&&(this.error=t.error),this.authServer=new u.OAuthAuthorizationServer(this.clientStorage,o,e,t),u.setParameter("loginUrl",u.ParamType.String,this,t,"LOGIN_URL"),u.setParameter("refreshTokenType",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_TYPE"),u.setParameter("refreshTokenCookieName",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_NAME"),u.setParameter("refreshTokenCookieDomain",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_DOMAIN"),u.setParameter("refreshTokenCookieHttpOnly",u.ParamType.Boolean,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_HTTPONLY"),u.setParameter("refreshTokenCookiePath",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_PATH"),u.setParameter("refreshTokenCookieSecure",u.ParamType.Boolean,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_SECURE"),u.setParameter("refreshTokenCookieSameSite",u.ParamType.String,this,t,"OAUTH_REFRESH_TOKEN_COOKIE_SAMESITE"),u.setParameter("authorizeEndpointUrl",u.ParamType.String,this,t,"OAUTH_AUTHORIZE_ENDPOINT"),u.setParameter("tokenEndpointUrl",u.ParamType.String,this,t,"OAUTH_TOKEN_ENDPOINT"),u.setParameter("jwksEndpointUrl",u.ParamType.String,this,t,"OAUTH_JWKS_ENDPOINT"),this.refreshTokenType!="json"&&(((n=this.svelteKitServer.sessionServer)==null?void 0:n.enableCsrfProtection)==!0?this.csrfTokens=this.svelteKitServer.sessionServer.sessionManager.csrfTokens:this.csrfTokens=new u.DoubleSubmitCsrfToken(t.doubleSubmitCookieOptions))}oidcConfiguration(){return this.authServer.oidcConfiguration({authorizeEndpoint:this.authorizeEndpointUrl,tokenEndpoint:this.tokenEndpointUrl,jwksUri:this.jwksEndpointUrl,additionalClaims:[]})}async authorize(s,i,{responseType:o,client_id:e,redirect_uri:t,scope:n,state:a,codeChallenge:c,codeChallengeMethod:l}){let h,d,f;if(i){const g=await this.authServer.authorizeGetEndpoint({responseType:o,client_id:e,redirect_uri:t,scope:n,state:a,codeChallenge:c,codeChallengeMethod:l,user:s.locals.user});if(f=g.code,h=g.error,d=g.error_description,h||!f){const E=r.CrossauthError.fromOAuthError(h??"server_error",d??"Neither code nor error received");return r.CrossauthLogger.logger.error(r.j({cerr:E})),{ok:!1,error:h,error_description:d}}throw this.redirect(302,this.authServer.redirect_uri(t,f,a))}else{const g=new r.CrossauthError(r.ErrorCode.Unauthorized,"You have not granted access");r.CrossauthLogger.logger.debug(r.j({err:g})),r.CrossauthLogger.logger.error(r.j({cerr:g})),r.CrossauthLogger.logger.error(r.j({msg:d,errorCode:g.code,errorCodeName:g.codeName}));try{throw u.OAuthClientManager.validateUri(t),this.redirect(302,t+"?error=access_denied&error_description="+encodeURIComponent("Access was not granted"))}catch(E){if(C.isSvelteKitError(E)||C.isSvelteKitRedirect(E))throw E;return r.CrossauthLogger.logger.error(r.j({msg:`Couldn't send error message ${g.codeName} to ${t}}`})),{ok:!1,error:"server_error",error_description:"Redirect Uri is not valid"}}}}async createCsrfToken(){if(!this.csrfTokens)throw new r.CrossauthError(r.ErrorCode.Configuration,"CSRF tokens not enabled");this.csrfTokens.makeCsrfCookie(this.csrfTokens.createCsrfToken());const s=this.csrfTokens.createCsrfToken(),i=this.csrfTokens.makeCsrfFormOrHeaderToken(s);return{csrfCookie:this.csrfTokens.makeCsrfCookie(s),csrfFormOrHeaderValue:i}}setRefreshTokenCookie(s,i,o){if(!this.refreshTokenCookieName)return;let e=o?new Date(Date.now()+o*1e3).toUTCString():void 0,t={path:this.refreshTokenCookiePath??"/"};e&&(t.expires=new Date(e)),this.refreshTokenCookieSameSite&&(t.sameSite=this.refreshTokenCookieSameSite),this.refreshTokenCookieDomain&&(t.domain=this.refreshTokenCookieDomain),this.refreshTokenCookieHttpOnly==!0&&(t.httpOnly=!0),this.refreshTokenCookieSecure==!0&&(t.secure=!0),s.cookies.set(this.refreshTokenCookieName,i,t)}requireGetParam(s,i){if(!s.url.searchParams.get(i))return{ok:!1,error:"invalid_request",error_description:i+" is required"}}requireBodyParam(s,i){if(!(i in s))return{ok:!1,error:"invalid_request",error_description:i+" is required"}}getAuthorizeQuery(s){let i=this.requireGetParam(s,"response_type");if(i)return{error:i};if(i=this.requireGetParam(s,"client_id"),i)return{error:i};if(i=this.requireGetParam(s,"redirect_uri"),i)return{error:i};if(i=this.requireGetParam(s,"state"),i)return{error:i};const o=s.url.searchParams.get("response_type")??"",e=s.url.searchParams.get("client_id")??"",t=s.url.searchParams.get("redirect_uri")??"",n=s.url.searchParams.get("scope")??void 0,a=s.url.searchParams.get("state")??"",c=s.url.searchParams.get("code_challenge")??void 0,l=s.url.searchParams.get("code_challenge_method")??void 0;return{query:{response_type:o,client_id:e,redirect_uri:t,scope:n,state:a,code_challenge:c,code_challenge_method:l},error:{error:"Unknown error",error_description:"Unknown error",ok:!0}}}async getMfaChallengeQuery(s){let i=new S;await i.loadData(s);const o=i.toObject();let e=this.requireBodyParam(o,"client_id");if(e)return{error:e};if(e=this.requireBodyParam(o,"challenge_type"),e)return{error:e};if(e=this.requireBodyParam(o,"mfa_token"),e)return{error:e};if(e=this.requireBodyParam(o,"authenticator_id"),e)return{error:e};const t=o.client_id??"",n=o.challenge_type??"",a=o.mfa_token??"",c=o.authenticator_id??"",l=o.client_secret??void 0;return{query:{client_id:t,client_secret:l,challenge_type:n,mfa_token:a,authenticator_id:c},error:{error:"Unknown error",error_description:"Unknown error",ok:!0}}}async mfaAuthenticators(s){var n;const i=(n=s.request.headers.get("authorization"))==null?void 0:n.split(" ");if(!i||i.length!=2)return{error:"access_denied",error_description:"Invalid authorization header"};const o=i[1],e=await this.authServer.mfaAuthenticatorsEndpoint(o);if(e.authenticators)return e.authenticators;const t=r.CrossauthError.fromOAuthError(e.error??"server_error");return{error:t.oauthErrorCode,error_description:t.message}}async mfaChallenge(s){let i=await this.getMfaChallengeQuery(s);if(!i.query)return i.error;let o=i.query;return await this.authServer.mfaChallengeEndpoint(o.mfa_token,o.client_id,o.client_secret,o.challenge_type,o.authenticator_id)}getClientIdAndSecret(s,i){let o=s.client_id,e=s.client_secret;const t=i.request.headers.get("authorization");if(t){let n,a;const c=t.split(" ");if(c.length==2&&c[0].toLocaleLowerCase()=="basic"){const h=u.Crypto.base64Decode(c[1]).split(":",2);h.length==2&&(n=h[0],a=h[1])}n==null||a==null?r.CrossauthLogger.logger.warn(r.j({msg:"Ignoring malform authenization header "+t})):(o=n,e=a)}return{client_id:o,client_secret:e}}async applyUserCode(s,i,o){var e,t,n;try{const a=await this.authServer.deviceEndpoint({userCode:s,user:o});if(a.error)return{ok:!1,completed:!1,retryAllowed:!1,error:a.error,error_description:a.error_description};if(!a.client_id)return r.CrossauthLogger.logger.error(r.j({msg:"No client id found for user code",userCodeHash:u.Crypto.hash(s),ip:i.request.referrer,username:(e=i.locals.user)==null?void 0:e.username})),{ok:!1,completed:!1,retryAllowed:!1,error:"server_error",error_description:"No client id found for user code"};if(a.error=="access_denied")return r.CrossauthLogger.logger.error(r.j({msg:"Incorrect user code given",userCodeHash:u.Crypto.hash(s),ip:i.request.referrer,username:(t=i.locals.user)==null?void 0:t.username})),this.authServer.userCodeThrottle>0&&await(h=>new Promise(d=>setTimeout(d,h)))(this.authServer.userCodeThrottle),{ok:!1,completed:!1,retryAllowed:!0,error:a.error,error_description:a.error_description};if(a.error=="expired_token")return r.CrossauthLogger.logger.error(r.j({msg:"Expired user code",userCodeHash:u.Crypto.hash(s),ip:i.request.referrer,username:(n=i.locals.user)==null?void 0:n.username})),{ok:!1,completed:!1,retryAllowed:!1,error:a.error,error_description:a.error_description};const c=await this.clientStorage.getClientById(a.client_id);return a.scopeAuthorizationNeeded?{ok:!0,completed:!1,retryAllowed:!0,authorizationNeeded:{user:o,client_id:a.client_id,client_name:c.client_name,scope:a.scope,scopes:a.scope?a.scope.split(" "):[],csrfToken:i.locals.csrfToken},user:i.locals.user,csrfToken:i.locals.csrfToken,user_code:s}:{ok:!0,completed:!0,retryAllowed:!1,user:i.locals.user,csrfToken:i.locals.csrfToken}}catch(a){const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug(r.j({err:c})),r.CrossauthLogger.logger.error(r.j({msg:c.message,cerr:c})),{ok:!1,completed:!1,retryAllowed:!0,error:c.oauthErrorCode,error_description:c.message}}}baseEndpoint(s){return{user:s.locals.user,csrfToken:s.locals.csrfToken}}async storeSessionData(s,i,o){var e,t,n,a;if(this.svelteKitServer.sessionServer){let c=(e=this.svelteKitServer.sessionServer)==null?void 0:e.getSessionCookieValue(s);c?await((n=this.svelteKitServer.sessionAdapter)==null?void 0:n.updateSessionData(s,o,i)):c=await((t=this.svelteKitServer.sessionServer)==null?void 0:t.createAnonymousSession(s,{[o]:i}))}else await((a=this.svelteKitServer.sessionAdapter)==null?void 0:a.updateSessionData(s,o,i))}async redirectError(s,i,o){throw s?this.redirect(302,s+"?error="+encodeURIComponent(i)+"&error_description="+encodeURIComponent(o)):this.error(500,o)}}async function M(p,s,i){return r.CrossauthLogger.logger.debug(r.j({err:i})),r.CrossauthLogger.logger.error(r.j({cerr:i})),m.json({ok:!1,status:i.httpStatus,errorMessage:i.message,errorMessages:i.messages,errorCode:i.code,errorCodeName:i.codeName},{status:i.httpStatus})}async function Z(p,s,i){var o;throw(o=p.oAuthClient)==null?void 0:o.error(i.httpStatus,i.message)}function b(p){let s;if(p)try{s=JSON.parse(u.Crypto.base64Decode(p.split(".")[1]))}catch(i){const o=r.CrossauthError.asCrossauthError(i);r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({msg:"Couldn't decode token",cerr:o}))}return s}async function q(p,s,i,o,e){let t={ok:!0,...p};return s.jwtTokens.includes("id")&&(t.id_payload=p.id_payload??b(p.id_token)),m.json(t)}function I(p,s){var i;if(p.access_token)try{if(p.access_token&&s.includes("access")){const o=P.jwtDecode(p.access_token),e=o.jti?o.jti:o.sid?o.sid:"",t=e?u.Crypto.hash(e):void 0;r.CrossauthLogger.logger.debug(r.j({msg:"Got access token",accessTokenHash:t}))}}catch(o){r.CrossauthLogger.logger.debug(r.j({err:o}))}if(p.id_token)try{if(p.id_token&&s.includes("id")){const o=p.id_payload??P.jwtDecode(p.id_token);if(o){const e=o.jti?o.jti:o.sid?o.sid:"",t=e?u.Crypto.hash(e):void 0;r.CrossauthLogger.logger.debug(r.j({msg:"Got id token",idTokenHash:t}))}}}catch(o){r.CrossauthLogger.logger.debug(r.j({err:o}))}if(p.refresh_token&&s.includes("refresh"))try{if(p.refresh_token){const o=(i=P.jwtDecode(p.refresh_token))==null?void 0:i.jti,e=o?u.Crypto.hash(o):void 0;r.CrossauthLogger.logger.debug(r.j({msg:"Got refresh token",refreshTokenHash:e}))}}catch(o){r.CrossauthLogger.logger.debug(r.j({err:o}))}}async function R(p,s,i){if(!s.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot update session data if not using sessions");let o=p.expires_in;if(!o&&p.access_token&&s.jwtTokens.includes("access")){const n=P.jwtDecode(p.access_token);n.exp&&(o=n.exp)}if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"OAuth server did not return an expiry for the access token");const e=Date.now()+o*1e3;let t={...p,expires_at:e};if("id_token"in p){let n=p.id_payload??b(p.id_token);n&&(t.id_payload=n)}await s.storeSessionData(i,t)}async function rr(p,s,i,o,e){if(p.error){const t=r.CrossauthError.fromOAuthError(p.error,p.error_description);return s.errorFn(s.server,i,t)}I(p,s.jwtTokens);try{if(p.access_token||p.id_token||p.refresh_token){await R(p,s,i);const t=p.id_payload??b(p.id_token);t&&await e(i,t)}if(!o)return s.redirect(302,s.authorizedUrl)}catch(t){if(C.isSvelteKitError(t)||C.isSvelteKitRedirect(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.debug(r.j({cerr:n,msg:"Error receiving tokens"})),s.errorFn(s.server,i,n)}}async function er(p,s,i,o,e){if(p.error){const t=r.CrossauthError.fromOAuthError(p.error,p.error_description);return s.errorFn(s.server,i,t)}I(p,s.jwtTokens);try{if(p.access_token||p.id_token||p.refresh_token){await R(p,s,i);const t=p.id_payload??b(p.id_token);t&&await e(i,t)}return m.json({ok:!0,...p})}catch(t){if(C.isSvelteKitError(t)||C.isSvelteKitRedirect(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.debug(r.j({cerr:n,msg:"Error receiving tokens"})),s.errorFn(s.server,i,n)}}async function sr(p,s,i,o,e){if(p.error)return{ok:!1,error:p.error,error_description:p.error_description};I(p,s.jwtTokens);try{(p.access_token||p.id_token||p.refresh_token)&&await R(p,s,i);let t={ok:!0,...p};return s.jwtTokens.includes("id")&&(t.id_payload=p.id_payload??b(p.id_token)),t.id_payload&&await e(i,t.id_payload),t}catch(t){if(C.isSvelteKitError(t)||C.isSvelteKitRedirect(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.debug(r.j({cerr:n,msg:"Error receiving tokens"})),{ok:!1,error:n.oauthErrorCode,error_description:n.message}}}async function or(p,s,i,o){if(p.error)return{ok:!1,error:p.error,error_description:p.error_description};I(p,s.jwtTokens);try{let e={ok:!0,...p};return s.jwtTokens.includes("id")&&(e.id_payload=p.id_payload??b(p.id_token)),e}catch(e){if(C.isSvelteKitError(e)||C.isSvelteKitRedirect(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.debug(r.j({cerr:t,msg:"Error receiving tokens"})),{ok:!1,error:t.oauthErrorCode,error_description:t.message}}}class j extends u.OAuthClientBackend{constructor(s,i,o){if(super(i,o),this.sessionDataName="oauth",this.receiveTokenFn=q,this.errorFn=M,this.loginUrl="/login",this.validFlows=[r.OAuthFlows.All],this.authorizedUrl="",this.autoRefreshActive={},this.loginProtectedFlows=[],this.tokenResponseType="sendJson",this.errorResponseType="sendJson",this.bffEndpoints=[],this.bffEndpointName="bff",this.tokenEndpoints=[],this.bffMaxTries=1,this.bffSleepMilliseconds=500,this.jwtTokens=["access","id","refresh"],this.testMiddleware=!1,this.testEvent=void 0,this.authorizationCodeFlowEndpoint={get:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use load not get");return this.errorFn(this.server,e,t)}try{if(!this.validFlows.includes(r.OAuthFlows.AuthorizationCode)){const d=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return this.errorFn(this.server,e,d)}if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Need session server or adapter for authorization code flow");let t=e.url.searchParams.get("scope")??void 0;t==""&&(t=void 0);const n=this.randomValue(this.stateLength),a={scope:t,state:n};await this.storeSessionData(e,a);const{url:c,error:l,error_description:h}=await this.startAuthorizationCodeFlow(n,t);if(l||!c){const d=r.CrossauthError.fromOAuthError(l??"server_error",h);return await this.errorFn(this.server,e,d)}throw this.oauthLogFetch?r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect",url:c})):r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect"})),this.redirect(302,c)}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),this.errorFn(this.server,e,n)}},load:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad"){const t=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return{ok:!1,error:t.oauthErrorCode,error_description:t.message}}try{if(!this.validFlows.includes(r.OAuthFlows.AuthorizationCode)){const d=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return{ok:!1,error:d.oauthErrorCode,error_description:d.message}}if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Need session server or adapter for authorization code flow");let t=e.url.searchParams.get("scope")??void 0;t==""&&(t=void 0);const n=this.randomValue(this.stateLength),a={scope:t,state:n};await this.storeSessionData(e,a);const{url:c,error:l,error_description:h}=await this.startAuthorizationCodeFlow(n,t);if(l||!c){const d=r.CrossauthError.fromOAuthError(l??"server_error",h);return{ok:!1,error:d.oauthErrorCode,error_description:d.message}}throw this.oauthLogFetch?r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect",url:c})):r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect"})),this.redirect(302,c)}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),{ok:!1,error:n.oauthErrorCode,error_description:n.message}}}},this.authorizationCodeFlowWithPKCEEndpoint={get:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use load not get");return this.errorFn(this.server,e,t)}try{if(!this.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)){const g=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return this.errorFn(this.server,e,g)}if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Need session server or adapter for authorization code flow");let t=e.url.searchParams.get("scope")??void 0;t==""&&(t=void 0);const n=this.randomValue(this.stateLength),{codeChallenge:a,codeVerifier:c}=await this.codeChallengeAndVerifier(),l={scope:t,state:n,codeChallenge:a,codeVerifier:c};await this.storeSessionData(e,l);const{url:h,error:d,error_description:f}=await this.startAuthorizationCodeFlow(n,t,a,!0);if(d||!h){const g=r.CrossauthError.fromOAuthError(d??"server_error",f);return await this.errorFn(this.server,e,g)}throw this.oauthLogFetch?r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect",url:h})):r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect"})),this.redirect(302,h)}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),m.json({error:n.oauthErrorCode,error_description:n.message},{status:n.httpStatus})}},load:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use get not load");return{ok:!1,error:t.oauthErrorCode,error_description:t.message}}try{if(!this.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)){const g=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flow is not supported");return{ok:!1,error:g.oauthErrorCode,error_description:g.message}}if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Need session server or adapter for authorization code flow");let t=e.url.searchParams.get("scope")??void 0;t==""&&(t=void 0);const n=this.randomValue(this.stateLength),{codeChallenge:a,codeVerifier:c}=await this.codeChallengeAndVerifier(),l={scope:t,state:n,codeChallenge:a,codeVerifier:c};await this.storeSessionData(e,l);const{url:h,error:d,error_description:f}=await this.startAuthorizationCodeFlow(n,t,a,!0);if(d||!h){const g=r.CrossauthError.fromOAuthError(d??"server_error",f);return{ok:!1,error:g.oauthErrorCode,error_description:g.message}}throw this.oauthLogFetch?r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect",url:h})):r.CrossauthLogger.logger.debug(r.j({msg:"OAuth redirect"})),this.redirect(302,h)}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),{ok:!1,error:n.oauthErrorCode,error_description:n.message}}}},this.redirectUriEndpoint={get:async e=>{var t;if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const n=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use load not get");return this.errorFn(this.server,e,n)}try{if(!(this.validFlows.includes(r.OAuthFlows.AuthorizationCode)||this.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)||this.validFlows.includes(r.OAuthFlows.OidcAuthorizationCode))){const f=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flows are not supported");return this.errorFn(this.server,e,f)}r.CrossauthLogger.logger.debug(r.j({msg:"redirectUriEndpoint, token response type "+this.tokenResponseType}));const n=e.url.searchParams.get("code")??"",a=e.url.searchParams.get("state")??void 0,c=e.url.searchParams.get("error")??void 0,l=e.url.searchParams.get("error")??void 0,h=await((t=this.server.sessionAdapter)==null?void 0:t.getSessionData(e,this.sessionDataName));if((h==null?void 0:h.state)!=a)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"State does not match");const d=this.errorIfIdTokenInvalid(await this.redirectEndpoint(n,h==null?void 0:h.scope,h==null?void 0:h.codeVerifier,c,l));if(d.error)return this.errorFn(this.server,e,r.CrossauthError.fromOAuthError(d.error,d.error_description));if(d.error){const f=r.CrossauthError.fromOAuthError(d.error,d.error_description);return await this.errorFn(this.server,e,f)}return await this.receiveTokenFn(d,this,e,!1,this.setEventLocalsUser)}catch(n){if(C.isSvelteKitRedirect(n)||C.isSvelteKitError(n))throw n;const a=r.CrossauthError.asCrossauthError(n);return r.CrossauthLogger.logger.debug({err:n}),r.CrossauthLogger.logger.error({cerr:n}),this.errorFn(this.server,e,a)}},load:async e=>{var t;if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad"){const n=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use get not load");return{ok:!1,error:n.oauthErrorCode,error_description:n.message}}try{if(!(this.validFlows.includes(r.OAuthFlows.AuthorizationCode)||this.validFlows.includes(r.OAuthFlows.AuthorizationCodeWithPKCE)||this.validFlows.includes(r.OAuthFlows.OidcAuthorizationCode))){const g=new r.CrossauthError(r.ErrorCode.Unauthorized,"Authorization flows are not supported");return{ok:!1,error:g.oauthErrorCode,error_description:g.message}}const n=e.url.searchParams.get("code")??"",a=e.url.searchParams.get("state")??void 0,c=e.url.searchParams.get("error")??void 0,l=e.url.searchParams.get("error")??void 0,h=await((t=this.server.sessionAdapter)==null?void 0:t.getSessionData(e,this.sessionDataName));if((h==null?void 0:h.state)!=a)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"State does not match");const d=this.errorIfIdTokenInvalid(await this.redirectEndpoint(n,h==null?void 0:h.scope,h==null?void 0:h.codeVerifier,c,l));if(d.error)return{ok:!1,error:d.error,error_description:d.error_description};if(d.error){const g=r.CrossauthError.fromOAuthError(d.error,d.error_description);return{ok:!1,error:g.oauthErrorCode,error_description:g.message}}const f=await this.receiveTokenFn(d,this,e,!1,this.setEventLocalsUser);return f instanceof Response?{ok:!1,error:"server_error",error_description:"When using load, receiveTokenFn should return an object not a Response"}:f==null?{ok:!1,error:"server_error",error_description:"No response received from receiveTokenFn"}:f.error?{ok:!1,error:f.error,error_description:f.error_description}:{...f}}catch(n){if(C.isSvelteKitRedirect(n)||C.isSvelteKitError(n))throw n;const a=r.CrossauthError.asCrossauthError(n);return r.CrossauthLogger.logger.debug({err:n}),r.CrossauthLogger.logger.error({cerr:n}),{ok:!1,error:a.oauthErrorCode,error_description:a.message}}}},this.clientCredentialsFlowEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const a=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,a)}let t;try{if(!this.validFlows.includes(r.OAuthFlows.ClientCredentials)){const l=new r.CrossauthError(r.ErrorCode.Unauthorized,"Client credentials flow is not supported");return this.errorFn(this.server,e,l)}var n=new S;await n.loadData(e),t=n.toObject();const a=this.errorIfIdTokenInvalid(await this.clientCredentialsFlow(t==null?void 0:t.scope));if(a.error){const l=r.CrossauthError.fromOAuthError(a.error,a.error_description);return await this.errorFn(this.server,e,l)}const c=await this.receiveTokenFn(a,this,e,!1,this.setEventLocalsUser);return c instanceof Response?c:this.pack(c)}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:a}),r.CrossauthLogger.logger.error({cerr:a}),this.errorFn(this.server,e,c)}},actions:{default:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use post not load");let t;try{if(!this.validFlows.includes(r.OAuthFlows.ClientCredentials))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Client credentials flow is not supported");var n=new S;await n.loadData(e),t=n.toObject();const a=this.errorIfIdTokenInvalid(await this.clientCredentialsFlow(t==null?void 0:t.scope));if(a.error)throw r.CrossauthError.fromOAuthError(a.error,a.error_description);return await this.receiveTokenFn(a,this,e,!1,this.setEventLocalsUser)??{}}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:a}),r.CrossauthLogger.logger.error({cerr:a}),{ok:!1,error:c.oauthErrorCode,error_description:c.message}}}}},this.refreshTokenFlowEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const a=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,a)}let t;try{if(!this.validFlows.includes(r.OAuthFlows.RefreshToken)){const h=new r.CrossauthError(r.ErrorCode.Unauthorized,"Refresh token flow is not supported");return this.errorFn(this.server,e,h)}var n=new S;if(await n.loadData(e),t=n.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(e))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(h){if(C.isSvelteKitError(h)||C.isSvelteKitRedirect(h))throw h;const d=new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present");return this.errorFn(this.server,e,d)}let a=t.refresh_token;if(!a&&this.server.sessionAdapter){const h=await this.server.sessionAdapter.getSessionData(e,this.sessionDataName);if(!(h!=null&&h.refresh_token)){const d=new r.CrossauthError(r.ErrorCode.BadRequest,"No refresh token in session or in parameters");return this.errorFn(this.server,e,d)}a=h.refresh_token}if(!a){const h=new r.CrossauthError(r.ErrorCode.BadRequest,"No refresh token supplied");return this.errorFn(this.server,e,h)}const c=this.errorIfIdTokenInvalid(await this.refreshTokenFlow(a)),l=await this.receiveTokenFn(c,this,e,!1,this.setEventLocalsUser);if(c&&l instanceof Response)return l;throw new r.CrossauthError(r.ErrorCode.UnknownError,"Receive token function did not return a Response")}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:a}),r.CrossauthLogger.logger.error({cerr:a}),this.errorFn(this.server,e,c)}},actions:{default:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use post not load");let t;try{if(!this.validFlows.includes(r.OAuthFlows.RefreshToken)){const h=new r.CrossauthError(r.ErrorCode.Unauthorized,"Refresh token flow is not supported");return this.errorFn(this.server,e,h)}var n=new S;if(await n.loadData(e),t=n.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(e))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(h){throw C.isSvelteKitError(h)||C.isSvelteKitRedirect(h)?h:new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present")}let a=t.refresh_token;if(!a&&this.server.sessionAdapter){const h=await this.server.sessionAdapter.getSessionData(e,this.sessionDataName);if(!(h!=null&&h.refresh_token))throw new r.CrossauthError(r.ErrorCode.BadRequest,"No refresh token in session or in parameters");a=h.refresh_token}if(!a)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No refresh token supplied");const c=this.errorIfIdTokenInvalid(await this.refreshTokenFlow(a)),l=await this.receiveTokenFn(c,this,e,!1,this.setEventLocalsUser)??{};if(l instanceof Response)throw new r.CrossauthError(r.ErrorCode.Configuration,"Refresh token flow should return an object not Response");return l}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:a}),r.CrossauthLogger.logger.error({cerr:a}),{ok:!1,error:c.oauthErrorCode,error_description:c.message}}}}},this.refreshTokensIfExpiredEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,t)}return this.pack(await this.refreshTokens(e,"post",!0))},actions:{default:async e=>{if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use post not load");return this.refreshTokens(e,"page",!0)}}},this.autoRefreshTokensIfExpiredEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,t)}return this.pack(await this.refreshTokens(e,"silent",!0))}},this.autoRefreshTokensEndpoint={post:async e=>{if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,e,t)}return this.pack(await this.refreshTokens(e,"silent",!1))}},this.startDeviceCodeFlowEndpoint={actions:{default:async e=>await this.startDeviceCodeFlow_internal(e)},post:async e=>{const t=await this.startDeviceCodeFlow_internal(e);if(t.error){const n=r.CrossauthError.fromOAuthError(t.error,t.error_description);return m.json(t,{status:n.httpStatus})}return m.json(t)}},this.pollDeviceCodeFlowEndpoint={actions:{default:async e=>{const t=await this.pollDeviceCodeFlow_internal(e);return t instanceof Response?this.unpack(t):t??{}}},post:async e=>{const t=await this.pollDeviceCodeFlow_internal(e);if(t instanceof Response)return t;if(t==null)return new Response(null,{status:204});if(t.error){const n=r.CrossauthError.fromOAuthError(t.error,t.error_description);return m.json(t,{status:n.httpStatus})}return m.json(t)}},this.passwordFlowEndpoint={post:async e=>await this.passwordFlow_post(e,(t,n)=>this.passwordPost(t,n)),actions:{password:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordPost(t,n)),passwordOtp:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordOtp(t,n)),passwordOob:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordOob(t,n))}},this.passwordOtpEndpoint={post:async e=>await this.passwordFlow_post(e,(t,n)=>this.passwordOtp(t,n)),actions:{default:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordOtp(t,n))}},this.passwordOobEndpoint={post:async e=>await this.passwordFlow_post(e,(t,n)=>this.passwordOob(t,n)),actions:{default:async e=>await this.passwordFlow_action(e,(t,n)=>this.passwordOob(t,n))}},this.deleteTokensEndpoint={post:async e=>{var t,n;try{return await this.deleteSessionData(e),m.json({ok:!0})}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),m.json({ok:!1,user:(t=this.server.sessionAdapter)==null?void 0:t.getUser(e),csrfToken:(n=this.server.sessionAdapter)==null?void 0:n.getCsrfToken(e),errorCode:c.code,errorCodeName:c.codeName,errorMessage:c.message},{status:c.httpStatus})}},actions:{default:async e=>{var t,n;try{return await this.deleteSessionData(e),{ok:!0}}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;const c=r.CrossauthError.asCrossauthError(a);return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),{ok:!1,user:(t=this.server.sessionAdapter)==null?void 0:t.getUser(e),csrfToken:(n=this.server.sessionAdapter)==null?void 0:n.getCsrfToken(e),errorCode:c.code,errorCodeName:c.codeName,errorMessage:c.message}}}}},this.bffEndpoint={post:async e=>await this.bff(e),get:async e=>await this.bff(e),put:async e=>await this.bff(e),head:async e=>await this.bff(e),options:async e=>await this.bff(e),delete:async e=>await this.bff(e),patch:async e=>await this.bff(e),actions:{get:async e=>await this.unpack(await this.bff(e)),post:async e=>await this.unpack(await this.bff(e))}},this.allBffEndpoint={post:async e=>await this.allBff(e),get:async e=>await this.allBff(e),put:async e=>await this.allBff(e),head:async e=>await this.allBff(e),options:async e=>await this.allBff(e),delete:async e=>await this.allBff(e),patch:async e=>await this.allBff(e),actions:{get:async e=>await this.unpack(await this.allBff(e,{method:"GET"})),gpostet:async e=>await this.unpack(await this.allBff(e,{method:"POST"})),put:async e=>await this.unpack(await this.allBff(e,{method:"PUT"})),options:async e=>await this.unpack(await this.allBff(e,{method:"OPTIONS"})),delete:async e=>await this.unpack(await this.allBff(e,{method:"DELETE"})),patch:async e=>await this.unpack(await this.allBff(e,{method:"PATCH"}))}},this.accessTokenEndpoint={post:async e=>await this.tokens(e,"access_token"),actions:{default:async e=>await this.tokens(e,"access_token")}},this.haveAccessTokenEndpoint={post:async e=>await this.tokensResponse(e,"have_access_token"),actions:{default:async e=>await this.tokens(e,"have_access_token")}},this.refreshTokenEndpoint={post:async e=>await this.tokensResponse(e,"refresh_token"),actions:{default:async e=>await this.tokens(e,"refresh_token")}},this.haveRefreshTokenEndpoint={post:async e=>await this.tokensResponse(e,"have_refresh_token"),actions:{default:async e=>await this.tokens(e,"have_refresh_token")}},this.idTokenEndpoint={post:async e=>await this.tokensResponse(e,"id_token"),actions:{default:async e=>await this.tokens(e,"id_token")}},this.haveIdTokenEndpoint={post:async e=>await this.tokensResponse(e,"have_id_token"),actions:{default:async e=>await this.tokens(e,"have_id_token")}},this.tokensEndpoint={post:async e=>await this.tokensResponse(e,this.tokenEndpoints),actions:{default:async e=>await this.tokens(e,this.tokenEndpoints)}},this.server=s,u.setParameter("sessionDataName",u.ParamType.String,this,o,"OAUTH_SESSION_DATA_NAME"),u.setParameter("tokenResponseType",u.ParamType.String,this,o,"OAUTH_TOKEN_RESPONSE_TYPE"),u.setParameter("errorResponseType",u.ParamType.String,this,o,"OAUTH_ERROR_RESPONSE_TYPE"),u.setParameter("loginUrl",u.ParamType.String,this,o,"LOGIN_URL"),u.setParameter("bffEndpointName",u.ParamType.String,this,o,"OAUTH_BFF_ENDPOINT_NAME"),u.setParameter("bffBaseUrl",u.ParamType.String,this,o,"OAUTH_BFF_BASEURL"),u.setParameter("redirect_uri",u.ParamType.String,this,o,"OAUTH_REDIRECTURI",!0),u.setParameter("authorizedUrl",u.ParamType.String,this,o,"AUTHORIZED_URL",!1),u.setParameter("validFlows",u.ParamType.JsonArray,this,o,"OAUTH_validFlows"),u.setParameter("bffMaxTries",u.ParamType.Number,this,o,"OAUTH_BFF_MAX_RETRIES"),u.setParameter("bffSleepMilliseconds",u.ParamType.Number,this,o,"OAUTH_BFF_SLEEP_MILLISECONDS"),u.setParameter("jwtTokens",u.ParamType.JsonArray,this,o,"OAUTH_JWT_TOKENS"),this.bffEndpointName&&!this.bffEndpointName.startsWith("/")&&(this.bffEndpointName="/"+this.bffEndpointName),this.bffEndpointName&&this.bffEndpointName.endsWith("/")&&(this.bffEndpointName=this.bffEndpointName.substring(0,this.bffEndpointName.length-1)),this.bffBaseUrl&&this.bffBaseUrl.endsWith("/")&&(this.bffBaseUrl=this.bffBaseUrl.substring(0,this.bffBaseUrl.length-1)),o.redirect&&(this.redirect=o.redirect),o.error&&(this.error=o.error),this.validFlows.length==1&&this.validFlows[0]==r.OAuthFlows.All)this.validFlows=r.OAuthFlows.allFlows();else if(!r.OAuthFlows.areAllValidFlows(this.validFlows))throw new r.CrossauthError(r.ErrorCode.Configuration,"Invalid flows specificied in "+this.validFlows.join(","));try{new URL(this.redirect_uri??"")}catch{throw new r.CrossauthError(r.ErrorCode.Configuration,"Invalid redirect Uri "+this.redirect_uri)}if(o.tokenEndpoints&&(this.tokenEndpoints=o.tokenEndpoints),this.bffEndpointName.endsWith("/")&&(this.bffEndpointName=this.bffEndpointName.substring(0,this.bffEndpointName.length-1)),o.bffEndpoints&&(this.bffEndpoints=o.bffEndpoints.map(e=>({...e,methodsString:e.methods.map(t=>t)}))),this.bffEndpoints)for(let e of this.bffEndpoints)e.url.startsWith("/")||(e.url="/"+e.url);if(this.loginProtectedFlows.length==1&&this.loginProtectedFlows[0]==r.OAuthFlows.All)this.loginProtectedFlows=this.validFlows;else if(!r.OAuthFlows.areAllValidFlows(this.loginProtectedFlows))throw new r.CrossauthError(r.ErrorCode.Configuration,"Invalid flows specificied in "+this.loginProtectedFlows.join(","));if(this.tokenResponseType=="custom"&&!o.receiveTokenFn)throw new r.CrossauthError(r.ErrorCode.Configuration,"Token response type of custom selected but receiveTokenFn not defined");if(this.tokenResponseType=="custom"&&o.receiveTokenFn?this.receiveTokenFn=o.receiveTokenFn:this.tokenResponseType=="sendJson"?this.receiveTokenFn=q:this.tokenResponseType=="sendInPage"?this.receiveTokenFn=or:this.tokenResponseType=="saveInSessionAndLoad"?this.receiveTokenFn=sr:this.tokenResponseType=="saveInSessionAndRedirect"?this.receiveTokenFn=rr:this.tokenResponseType=="saveInSessionAndReturn"&&(this.receiveTokenFn=er),(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="saveInSessionAndRedirect")&&this.authorizedUrl=="")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is"+this.tokenResponseType+", must provide authorizedUrl");if((this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="saveInSessionAndRedirect")&&this.server.sessionAdapter==null)throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is"+this.tokenResponseType+", must activate the session server");if(this.errorResponseType=="custom"&&!o.errorFn)throw new r.CrossauthError(r.ErrorCode.Configuration,"Error response type of custom selected but errorFn not defined");if(this.errorResponseType=="custom"&&o.errorFn?this.errorFn=o.errorFn:this.errorResponseType=="sendJson"?this.errorFn=M:this.errorResponseType=="svelteKitError"&&(this.errorFn=Z),!o.redirect)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide the SvelteKit redirect function");if(!o.error&&this.errorResponseType=="svelteKitError")throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide the SvelteKit error function");if(this.loginProtectedFlows.length>0&&this.loginUrl=="")throw new r.CrossauthError(r.ErrorCode.Configuration,"loginUrl must be set if protecting oauth endpoints");this.hook=async({event:e})=>{if(r.CrossauthLogger.logger.debug(r.j({msg:"OAuth hook, user "+e.locals.user})),e.locals.user||!s.sessionAdapter)return;let t=await s.sessionAdapter.getSessionData(e,this.sessionDataName),n=!1;if(t&&t.id_payload){let a=t.expires_at;a&&a>Date.now()&&t.id_payload.sub&&(r.CrossauthLogger.logger.debug(r.j({msg:"ID token is valid"})),await this.setEventLocalsUser(e,t.id_payload),e.locals.user&&(n=!0))}if(!n&&t&&t.refresh_token){r.CrossauthLogger.logger.debug(r.j({msg:"No ID token found but refresh token found - attemping refresh flow"}));const a=await this.refreshTokens(e,"silent",!1);if(a!=null&&a.ok)await this.setEventLocalsUser(e,t.id_payload);else{const c=a instanceof Response||a==null?"server_error":a.error??"server_error",l=a instanceof Response||a==null?"Unknown error":a.error_description??"Unknown error",h=r.CrossauthError.fromOAuthError(c,l);r.CrossauthLogger.logger.debug(r.j({err:h})),r.CrossauthLogger.logger.warn(r.j({msg:"Error refreshing token",cerr:h}))}}this.testMiddleware&&(this.testEvent=e)}}async setEventLocalsUser(s,i){let o;s.locals.idTokenPayload=i;try{o=await this.userCreationFn(i,this.userStorage,this.userMatchField,this.idTokenMatchField),s.locals.user=o,s.locals.authType=o?"oidc":void 0,r.CrossauthLogger.logger.debug(r.j({msg:"Set locals.user to "+(o?o==null?void 0:o.username:"undefined")}))}catch(e){r.CrossauthLogger.logger.error(r.j({cerr:e})),s.locals.user=void 0,s.locals.authType=void 0}}async passwordPost(s,i){var o;try{let e=await this.passwordFlow(i.username,i.password,i.scope);if(e.error=="mfa_required"&&e.mfa_token&&this.validFlows.includes(r.OAuthFlows.PasswordMfa)){const t=e.mfa_token;let n=i.scope;if(n==""&&(n=void 0),e=this.errorIfIdTokenInvalid(await this.passwordMfa(t,n,s)),e.error)throw r.CrossauthError.fromOAuthError(e.error,e.error_description);return e}else if(e.error)throw r.CrossauthError.fromOAuthError(e.error,e.error_description);return e}catch(e){if(C.isSvelteKitError(e)||C.isSvelteKitRedirect(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.error(r.j({msg:"Error receiving token",cerr:t,user:(o=this.server.sessionAdapter)==null?void 0:o.getUser(s)})),r.CrossauthLogger.logger.debug(r.j({err:e})),{error:t.oauthErrorCode,error_description:t.message}}}async passwordMfa(s,i,o){const e=await this.mfaAuthenticators(s);if(e.error||!e.authenticators||!Array.isArray(e.authenticators)||e.authenticators.length==0||e.authenticators.length>1&&!e.authenticators[0].active)return{error:e.error??"server_error",error_description:e.error_description??"Unexpected error getting MFA authenticators"};const t=e.authenticators[0];if(t.authenticator_type=="otp"){const a=await this.mfaOtpRequest(s,t.id);if(a.error||a.challenge_type!="otp"){const c=r.CrossauthError.fromOAuthError(a.error??"server_error",a.error_description??"Invalid response from MFA OTP challenge");return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),{error:c.oauthErrorCode,error_description:c.message}}return{scope:i,mfa_token:s,challenge_type:a.challenge_type}}else if(t.authenticator_type=="oob"){const a=await this.mfaOobRequest(s,t.id);if(a.error||a.challenge_type!="oob"||!a.oob_code||a.binding_method!="prompt"){const c=r.CrossauthError.fromOAuthError(a.error??"server_error",a.error_description??"Invalid response from MFA OOB challenge");return r.CrossauthLogger.logger.debug({err:c}),r.CrossauthLogger.logger.error({cerr:c}),{error:c.oauthErrorCode,error_description:c.message}}return{scope:i,mfa_token:s,oob_channel:t.oob_channel,challenge_type:a.challenge_type,binding_method:a.binding_method,oob_code:a.oob_code,name:t.name}}const n=new r.CrossauthError(r.ErrorCode.UnknownError,"Unsupported MFA type "+t.authenticator_type+" returned");return{error:n.oauthErrorCode,error_description:n.message}}async passwordOtp(s,i){let o=i.scope;o==""&&(o=void 0);const e=this.errorIfIdTokenInvalid(await this.mfaOtpComplete(i.mfa_token,i.otp,o));if(e.error){const t=r.CrossauthError.fromOAuthError(e.error,e.error_description??"Error completing MFA");return{error:t.oauthErrorCode,error_description:t.message}}return e}async passwordOob(s,i){var t;let o=i.scope;o==""&&(o=void 0);const e=this.errorIfIdTokenInvalid(await this.mfaOobComplete(i.mfa_token,i.oob_code,i.binding_code,o));return e.error?(r.CrossauthLogger.logger.warn(r.j({msg:"Error completing MFA",user:(t=this.server.sessionAdapter)==null?void 0:t.getUser(s),hashedMfaToken:i.mfa_token?u.Crypto.hash(i.mfa_token):void 0})),{error:e.error,error_description:e.error_description}):e}async refresh(s,i,o,e,t){if(!t||!e)return s!="silent"?await this.receiveTokenFn({},this,i,!0,this.setEventLocalsUser):void 0;if(!o||t<=Date.now()){if(i.locals.sessionId&&this.autoRefreshActive[i.locals.sessionId])return;try{i.locals.sessionId&&(this.autoRefreshActive[i.locals.sessionId]=!0);const n=this.errorIfIdTokenInvalid(await this.refreshTokenFlow(e));if(!n.error&&!n.access_token&&(n.error="server_error",n.error_description="Unexpectedly did not receive error or access token"),!n.error){const l=await this.receiveTokenFn(n,this,i,s=="silent",this.setEventLocalsUser);if(s!="silent")return l}if(s!="silent"){const l=r.CrossauthError.fromOAuthError(n.error??"server_error",n.error_description);return s=="page"?this.errorFn(this.server,i,l):{error:l.oauthErrorCode,error_description:l.message}}let a=n.expires_in;if(!a&&n.access_token){const l=P.jwtDecode(n.access_token);l.exp&&(a=l.exp)}if(!a)throw new r.CrossauthError(r.ErrorCode.BadRequest,"OAuth server did not return an expiry for the access token");const c=new Date().getTime()+a*1e3;return{access_token:n.access_token,refresh_token:n.refresh_token,expires_in:n.expires_in,expires_at:c,error:n.error,error_description:n.error_description}}catch(n){if(C.isSvelteKitRedirect(n)||C.isSvelteKitError(n))throw n;if(r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n,msg:"Failed refreshing access token"})),s!="silent"){const a=r.CrossauthError.asCrossauthError(n);return s=="page"?this.errorFn(this.server,i,a):{error:a.oauthErrorCode,error_description:a.message}}return{error:"server_error",error_description:"Failed refreshing access token"}}finally{i.locals.sessionId&&i.locals.sessionId in this.autoRefreshActive&&delete this.autoRefreshActive[i.locals.sessionId]}}}async refreshTokens(s,i,o){try{if(!this.server.sessionAdapter)return{ok:!1,error:"server_error",error_description:"Refresh tokens if expired or silent refresh only available if sessions are enabled"};if(this.server.sessionAdapter.csrfProtectionEnabled()&&!this.server.sessionAdapter.getCsrfToken(s))return{ok:!1,error:"access_denied",error_description:"No CSRF token found"};const e=await this.server.sessionAdapter.getSessionData(s,this.sessionDataName);if(!(e!=null&&e.refresh_token)){if(i=="silent")return new Response(null,{status:204});throw new r.CrossauthError(r.ErrorCode.InvalidSession,"No tokens found in session")}let t=await this.refresh(i,s,o,e.refresh_token,e.expires_at);if(t&&"id_token"in t&&(t=this.errorIfIdTokenInvalid(t)),i=="silent"){if(t instanceof Response)throw new r.CrossauthError(r.ErrorCode.Configuration,"Unexpected error: refresh: mode is silent but didn't receive an object");return{ok:!0,expires_at:t==null?void 0:t.expires_at}}else if(i=="post"){if(t==null)return this.receiveTokenFn({},this,s,!1,this.setEventLocalsUser);if(t!=null){if(t instanceof Response)return t;throw new r.CrossauthError(r.ErrorCode.Configuration,"refreshTokenFn for post should return Response not object")}}}catch(e){if(C.isSvelteKitRedirect(e)||C.isSvelteKitError(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),i=="page"?this.errorFn(this.server,s,t):{ok:!1,error:t.oauthErrorCode,error_description:t.message}}}async passwordFlow_post(s,i){if(this.tokenResponseType=="saveInSessionAndLoad"||this.tokenResponseType=="sendInPage"){const t=new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use actions not post");return this.errorFn(this.server,s,t)}let o;try{if(!(this.validFlows.includes(r.OAuthFlows.Password)||this.validFlows.includes(r.OAuthFlows.PasswordMfa))){const a=new r.CrossauthError(r.ErrorCode.Unauthorized,"Password flow is not supported");return this.errorFn(this.server,s,a)}var e=new S;if(await e.loadData(s),o=e.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(a){if(C.isSvelteKitError(a)||C.isSvelteKitRedirect(a))throw a;const c=new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present");return this.errorFn(this.server,s,c)}const t=this.errorIfIdTokenInvalid(await i(s,o));if(!t)throw new r.CrossauthError(r.ErrorCode.UnknownError,"Password flow returned no data");if(t.error)return{ok:!1,...t};const n=await this.receiveTokenFn(t,this,s,!1,this.setEventLocalsUser);if(t&&n instanceof Response)return n;throw new r.CrossauthError(r.ErrorCode.UnknownError,"Receive token function did not return a Response")}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),this.errorFn(this.server,s,n)}}async passwordFlow_action(s,i){if(this.tokenResponseType=="sendJson"||this.tokenResponseType=="saveInSessionAndLoad")throw new r.CrossauthError(r.ErrorCode.Configuration,"If tokenResponseType is "+this.tokenResponseType+", use post not load");let o;try{if(!(this.validFlows.includes(r.OAuthFlows.Password)||this.validFlows.includes(r.OAuthFlows.PasswordMfa))){const a=new r.CrossauthError(r.ErrorCode.Unauthorized,"Password and Password MFA flows are not supported");return this.errorFn(this.server,s,a)}var e=new S;if(await e.loadData(s),o=e.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(a){throw C.isSvelteKitError(a)||C.isSvelteKitRedirect(a)?a:new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present")}const t=await i(s,o);if(!t)throw new r.CrossauthError(r.ErrorCode.UnknownError,"Password flow returned no data");if(t.error)return{ok:!1,...t};if(t.challenge_type){if(!this.validFlows.includes(r.OAuthFlows.PasswordMfa)){const a=new r.CrossauthError(r.ErrorCode.Unauthorized,"Password MFA flow is not supported");return this.errorFn(this.server,s,a)}return t}const n=await this.receiveTokenFn(t,this,s,!1,this.setEventLocalsUser)??{};if(n instanceof Response)throw new r.CrossauthError(r.ErrorCode.Configuration,"Refresh token flow should return an object not Response");return n}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:t}),r.CrossauthLogger.logger.error({cerr:t}),{ok:!1,error:n.oauthErrorCode,error_description:n.message}}}async bff(s,i={}){var e;try{if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Session server must be instantiated to use bff()");if(!this.server.oAuthClient)throw new r.CrossauthError(r.ErrorCode.Configuration,"OAuth Client not found");if(!this.bffBaseUrl)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set bffBaseUrl to use bff()");if(!this.bffEndpointName)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set bffEndpointName to use bff()");let t=i.url;if(!t){if(!s.url.pathname.startsWith(this.bffEndpointName))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Attempt to call BFF url with the wrong prefix");const n=s.url.pathname.substring(this.bffEndpointName.length);let a=((e=s.url.searchParams)==null?void 0:e.toString())??void 0;a&&a!=""&&(a="?"+a),t=new URL(this.bffBaseUrl+n+a)}i.headers||(i.headers=new Headers);for(let n=0;n<this.bffMaxTries;++n){n>0&&await new Promise(d=>setTimeout(d,this.bffSleepMilliseconds));const a=await this.server.sessionAdapter.getSessionData(s,this.sessionDataName);if(!a){if(n==this.bffMaxTries)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No access token found");continue}let c=a.access_token;if(a&&a.access_token){const d=await this.refresh("silent",s,!0,a.refresh_token,a.expires_at);if(d instanceof Response)throw new r.CrossauthError(r.ErrorCode.Configuration,"Expected object when refreshing tokens, not Response");if(d!=null&&d.access_token)c=d.access_token;else if(d!=null&&d.error)continue}i.headers.set("accept","application/json"),i.headers.set("content-type","application/json"),c&&i.headers.set("authorization","Bearer "+c);let l,h;if(s.request.body){var o=new S;await o.loadData(s),h=o.toObject()}if(r.CrossauthLogger.logger.debug(r.j({msg:"Calling BFF URL",url:t,method:s.request.method})),h?l=await fetch(t,{headers:i.headers,method:i.method??s.request.method,body:JSON.stringify(h??"{}")}):l=await fetch(t,{headers:i.headers,method:i.method??s.request.method}),l.status==401){if(n<this.bffMaxTries-1)continue;return l}else return l}return new Response(null,{status:401})}catch(t){if(C.isSvelteKitError(t)||C.isSvelteKitRedirect(t))throw t;const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug({err:n}),r.CrossauthLogger.logger.error({cerr:n}),m.json({error:n.oauthErrorCode,error_description:n.message},{status:n.httpStatus})}}async unpack(s){if(s.status==204)return{status:204,body:{}};try{return{status:s.status,body:await s.json()}}catch(i){if(C.isSvelteKitError(i)||C.isSvelteKitRedirect(i))throw i;const o=r.CrossauthError.asCrossauthError(i);return r.CrossauthLogger.logger.debug({err:o}),r.CrossauthLogger.logger.error({cerr:o}),{status:s.status,body:{},error:o.oauthErrorCode,error_description:o.message}}}pack(s){if(s instanceof Response)return s;let i=200;return(s==null?void 0:s.error)=="access_denied"?i=401:s!=null&&s.error?i=500:s||(i=204),m.json(s??null,{status:i})}async allBff(s,i={}){try{if(r.CrossauthLogger.logger.debug(r.j({msg:"Called allBff",url:s.url.toString()})),!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Session server must be instantiated to use bff()");if(!this.server.oAuthClient)throw new r.CrossauthError(r.ErrorCode.Configuration,"OAuth Client not found");if(!this.bffBaseUrl)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set bffBaseUrl to use bff()");if(!this.bffEndpointName)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set bffEndpointName to use bff()");if(!this.bffEndpoints||this.bffEndpoints.length==0)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Invalid BFF endpoint");if(!s.url.pathname.startsWith(this.bffEndpointName))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Attempt to call BFF url with the wrong prefix");const o=s.url.pathname.substring(this.bffEndpointName.length);let e;for(let t=0;t<this.bffEndpoints.length;++t){let n=this.bffEndpoints[t];if(n.matchSubUrls){let a=n.url,c=n.url;if(c.endsWith("/")||(c+="/"),n.methodsString.includes(s.request.method)&&(o.startsWith(c)||o==a)){e=t;break}}else{let a=n.url;if(n.methodsString.includes(s.request.method)&&o==a){e=t;break}}}if(e!=null)return await this.bff(s,i);throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Illegal BFF URL called "+s.url.toString())}catch(o){if(C.isSvelteKitError(o)||C.isSvelteKitRedirect(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug({err:e}),r.CrossauthLogger.logger.error({cerr:e}),m.json({error:e.oauthErrorCode,error_description:e.message},{status:e.httpStatus})}}tokenPayload(s,i,o,e){return s in i?o?{ok:!0}:e?s+"_payload"in i?i[s+"_payload"]:b(i[s]):i[s]:o?{ok:!1}:void 0}async tokens(s,i){try{let o=new S(!0);await o.loadData(s);const e=o.getAsBoolean("decode")??!0;if(!this.server.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Session server must be instantiated to use bff()");if(!this.server.oAuthClient)throw new r.CrossauthError(r.ErrorCode.Configuration,"OAuth Client not found");if(!this.tokenEndpoints||this.tokenEndpoints.length==0)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No tokens have been made available");let t=Array.isArray(i)?i:[i];const n=await this.server.sessionAdapter.getSessionData(s,this.sessionDataName);if(!n)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No access token found");let a={},c,l=!1;for(let h of t){if(!this.tokenEndpoints.includes(h))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Token type "+h+" may not be returned");l=!1;let d=h;h.startsWith("have_")&&(d=h.replace("have_",""),l=!0);const f=d.replace("_token",""),g=e&&this.jwtTokens.includes(f);let E=this.tokenPayload(d,n,l,g);l?a[h]=E.ok:E&&(a[h]=E),c=a[h]}return Array.isArray(i)?{status:200,body:a}:c?l?{status:200,body:typeof c=="boolean"?{ok:c}:c}:{status:200,body:c}:i.startsWith("have_")?{status:200,body:{ok:!1}}:{status:204}}catch(o){if(C.isSvelteKitError(o)||C.isSvelteKitRedirect(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug({err:e}),r.CrossauthLogger.logger.error({cerr:e}),{status:e.httpStatus,body:{error:e.oauthErrorCode,error_description:e.message}}}}async tokensResponse(s,i){const o=await this.tokens(s,i);return o.body?m.json(o.body,{status:o.status}):m.json(null,{status:o.status})}async startDeviceCodeFlow_internal(s){let i;try{if(!this.validFlows.includes(r.OAuthFlows.DeviceCode))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Device code flow is not supported");var o=new S;if(await o.loadData(s),i=o.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(c){throw C.isSvelteKitError(c)||C.isSvelteKitRedirect(c)?c:new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present")}let e=i.scope;e==""&&(e=void 0);let t=this.authServerBaseUrl;t.endsWith("/")||(t+="/"),t+=this.deviceAuthorizationUrl;const n=await this.startDeviceCodeFlow(t,e);let a;return n.verification_uri_complete&&await $.toDataURL(n.verification_uri_complete).then(c=>{a=c}).catch(c=>{r.CrossauthLogger.logger.debug(r.j({err:c})),r.CrossauthLogger.logger.warn(r.j({msg:"Couldn't generate verification URL QR Code"}))}),a?{verification_uri_qrdata:a,...n}:n}catch(e){if(C.isSvelteKitRedirect(e)||C.isSvelteKitError(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug({err:e}),r.CrossauthLogger.logger.error({cerr:e}),{error:t.oauthErrorCode,error_description:t.message}}}async pollDeviceCodeFlow_internal(s){let i;try{if(!this.validFlows.includes(r.OAuthFlows.DeviceCode))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"Device code flow is not supported");var o=new S;if(await o.loadData(s),i=o.toObject(),this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(n){throw C.isSvelteKitError(n)||C.isSvelteKitRedirect(n)?n:new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present")}let e=i.device_code;if(!e)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No device code given when polling for user authorization");const t=this.errorIfIdTokenInvalid(await this.pollDeviceCodeFlow(e));if(t.access_token&&!t.error)return await this.receiveTokenFn(t,this,s,!1,this.setEventLocalsUser);{if(t.error=="authorization_pending")return{ok:!0,...t};let n=t.error??"server_error",a=t.error_description??"Didn't receive an access token";const c=r.CrossauthError.fromOAuthError(n,a);return this.errorFn(this.server,s,c)}}catch(e){if(C.isSvelteKitRedirect(e)||C.isSvelteKitError(e))throw e;const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug({err:e}),r.CrossauthLogger.logger.error({cerr:e}),this.errorFn(this.server,s,t)}}async deleteSessionData(s){var i;if(this.server.sessionAdapter&&this.server.sessionAdapter.csrfProtectionEnabled())try{if(!this.server.sessionAdapter.getCsrfToken(s))throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}catch(o){if(C.isSvelteKitError(o)||C.isSvelteKitRedirect(o))throw o;const e=new r.CrossauthError(r.ErrorCode.Unauthorized,"CSRF token not present");return this.errorFn(this.server,s,e)}await((i=this.server.sessionAdapter)==null?void 0:i.deleteSessionData(s,this.sessionDataName))}async storeSessionData(s,i){var o,e,t,n;if(this.server.sessionServer){let a=(o=this.server.sessionServer)==null?void 0:o.getSessionCookieValue(s);a?await((t=this.server.sessionAdapter)==null?void 0:t.updateSessionData(s,this.sessionDataName,i)):a=await((e=this.server.sessionServer)==null?void 0:e.createAnonymousSession(s,{[this.sessionDataName]:i}))}else await((n=this.server.sessionAdapter)==null?void 0:n.updateSessionData(s,this.sessionDataName,i))}errorIfIdTokenInvalid(s){return s.id_token&&this.jwtTokens.includes("id"),s}}class tr{}class H extends u.OAuthResourceServer{constructor(s,i={}){if(super(s,i),this.errorBody={},this.protectedEndpoints={},this.protectedEndpointPrefixes=[],this.sessionDataName="oauth",this.tokenLocations=["header"],u.setParameter("errorBody",u.ParamType.Json,this,i,"OAUTH_RESSERVER_ACCESS_DENIED_BODY"),u.setParameter("tokenLocations",u.ParamType.JsonArray,this,i,"OAUTH_TOKEN_LOCATIONS"),u.setParameter("sessionDataName",u.ParamType.String,this,i,"OAUTH_SESSION_DATA_NAME"),this.userStorage=i.userStorage,this.sessionAdapter=i.sessionAdapter,i.protectedEndpoints){const o=/^[!#\$%&'\(\)\*\+,\.\/a-zA-Z\[\]\^_`-]+/;for(const[e,t]of Object.entries(i.protectedEndpoints)){if(!e.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"protected endpoints must be absolute paths without the protocol and hostname");t.scope&&t.scope.forEach(n=>{if(!o.test(n))throw new r.CrossauthError(r.ErrorCode.Configuration,"Illegal characters in scope "+n)})}this.protectedEndpoints={...i.protectedEndpoints};for(let e in i.protectedEndpoints){let t=this.protectedEndpoints[e];t.suburls==!0&&(e.endsWith("/")||(e+="/",this.protectedEndpoints[e]=t),this.protectedEndpointPrefixes.push(e))}}i.protectedEndpoints&&(this.hook=async({event:o})=>{var c,l;const e=o.url.pathname;let t=!1,n="";if(e in this.protectedEndpoints)t=!0,n=e;else for(let h of this.protectedEndpointPrefixes)e.startsWith(h)&&(t=!0),n=h;if(!t)return;const a=await this.authorized(o);if(!(o.locals.user&&o.locals.authType=="cookie"&&this.protectedEndpoints[n].acceptSessionAuthorization!=!0)){if(!a){o.locals.authError="access_denied",o.locals.authErrorDescription="No access token";const h=this.authenticateHeader(o);return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json","WWW-Authenticate":h},status:401})}if(!a.authorized){const h=this.authenticateHeader(o);return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json","WWW-Authenticate":h},status:401})}}if(a){if(o.locals.accessTokenPayload=a.tokenPayload,o.locals.user=a.user,(c=a.tokenPayload)!=null&&c.scope)if(Array.isArray(a.tokenPayload.scope)){let h=[];for(let d of a.tokenPayload.scope)typeof d=="string"&&h.push(d);o.locals.scope=h}else typeof a.tokenPayload.scope=="string"&&(o.locals.scope=a.tokenPayload.scope.split(" "));if(this.protectedEndpoints[n].scope){for(let h of this.protectedEndpoints[n].scope??[])if(!o.locals.scope||!o.locals.scope.includes(h)&&this.protectedEndpoints[n].acceptSessionAuthorization!=!0){r.CrossauthLogger.logger.warn(r.j({msg:"Access token does not have sufficient scope",username:(l=o.locals.user)==null?void 0:l.username,url:o.request.url})),o.locals.scope=void 0,o.locals.accessTokenPayload=void 0,o.locals.user=void 0,o.locals.authError="access_denied",o.locals.authErrorDescription="Access token does not have sufficient scope";const d=this.authenticateHeader(o);return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json","WWW-Authenticate":d},status:401})}}if(o.locals.authType="oauth",o.locals.authError=a==null?void 0:a.error,(a==null?void 0:a.error)=="access_denied"){const h=this.authenticateHeader(o);return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json","WWW-Authenticate":h},status:401})}else if(a!=null&&a.error)return new Response(JSON.stringify(this.errorBody),{headers:{"content-type":"application/json"},status:500});o.locals.authErrorDescription=a==null?void 0:a.error_description,r.CrossauthLogger.logger.debug(r.j({msg:"Resource server url",url:o.request.url,authorized:o.locals.accessTokenPayload!=null}))}})}authenticateHeader(s){const i=s.url.pathname;if(i in this.protectedEndpoints){let o="Bearer";return this.protectedEndpoints[i].scope&&(o+=' scope="'+(this.protectedEndpoints[i].scope??[]).join(" ")),o}return""}async authorized(s){try{let i;for(let e of this.tokenLocations)if(e=="header"){const t=await this.tokenFromHeader(s);if(t){i=t;break}}else{const t=await this.tokenFromSession(s);if(t){i=t;break}}let o;if(i){if(i.sub&&this.userStorage){const e=await this.userStorage.getUserByUsername(i.sub);e&&(o=e.user)}else i.sub&&(s.locals.user={id:i.userid??i.sub,username:i.sub,state:i.state??"active"});return{authorized:!0,tokenPayload:i,user:o}}else return{authorized:!1}}catch(i){const o=i;return r.CrossauthLogger.logger.debug(r.j({err:i})),r.CrossauthLogger.logger.error(r.j({cerr:o})),s.locals.authError="server_error",s.locals.authErrorDescription=o.message,{authorized:!1,error:"server_error",error_description:o.message}}}async tokenFromHeader(s){const i=s.request.headers.get("authorization");if(i&&i.startsWith("Bearer ")){const o=i.split(" ");if(o.length==2)return await this.accessTokenAuthorized(o[1])}}async tokenFromSession(s){if(!this.sessionAdapter)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot get session data if sessions not enabled");const i=await this.sessionAdapter.getSessionData(s,this.sessionDataName);if(i!=null&&i.session_token)return i.expires_at&&i.expires_at<Date.now()?void 0:await this.accessTokenAuthorized(i.session_token)}}function ir(p){return p.admin==!0}const U=class U{constructor({session:s,sessionAdapter:i,apiKey:o,oAuthAuthServer:e,oAuthClient:t,oAuthClients:n,oAuthResServer:a,options:c}){this.loginUrl="/login",this.audience="",this.dummyLoad=async h=>({}),this.dummyActions={},this.dummyBff=async h=>({status:500,body:{error:"Unimplemented"}}),c||(c={}),u.setParameter("loginUrl",u.ParamType.String,this,c,"LOGIN_URL",!1),c.isAdminFn&&(U.isAdminFn=c.isAdminFn);let l={};if(c.authenticators&&(l=c.authenticators),this.userStorage=c.userStorage,s){if(!l)throw new r.CrossauthError(r.ErrorCode.Configuration,"If using session management, must supply authenticators");this.sessionServer=new N(s.keyStorage,l,{...s.options,...c}),this.sessionAdapter=this.sessionServer}else i&&(this.sessionAdapter=i);if(o){if(!this.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must define a user storage if using API keys");this.apiKeyServer=new x(this.userStorage,o.keyStorage,{...c,...o.options})}if(e){let h={};this.loginUrl&&(h.loginUrl=this.loginUrl),this.oAuthAuthServer=new B(this,e.clientStorage,e.keyStorage,l,{...h,...c,...e.options})}if(t&&n)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot specify both oAuthClient and oAuthClients");if(t&&(this.oAuthClient=new j(this,t.authServerBaseUrl,{...c,...t.options})),n){this.oAuthClients=[];for(let h of n)this.oAuthClients.push(new j(this,h.authServerBaseUrl,{...c,...h.options}))}a&&(u.setParameter("audience",u.ParamType.String,this,c,"OAUTH_AUDIENCE",!0),this.oAuthResServer=new H([new u.OAuthTokenConsumer(this.audience,c)],{sessionAdapter:this.sessionAdapter,...a.options,...c})),this.hooks=async({event:h,resolve:d})=>{const f=await this.unresolvedHooks(h);return f instanceof Response?f:await d(f)}}async unresolvedHooks(s){var o,e;s.locals.user=void 0,s.locals.sessionId=void 0,s.locals.csrfToken=void 0,s.locals.authType=void 0,s.locals.scope=void 0;let i=!1;if(this.sessionServer){let t=await this.sessionServer.sessionHook({event:s});if(t.status==302){let a;for(let c of t.headers)c.name=="location"&&(a=c.value);a&&await this.sessionServer.redirect(302,a)}const n=this.userStorage?await this.sessionServer.twoFAHook({event:s}):void 0;if(!(n&&n.twofa)&&!s.locals.user){if(this.apiKeyServer&&await this.apiKeyServer.hook({event:s}),this.oAuthClient&&await this.oAuthClient.hook({event:s}),(o=this.oAuthResServer)!=null&&o.hook){const a=await this.oAuthResServer.hook({event:s});if(a)return a}if(i=!0,!s.locals.user){if(this.sessionServer.isLoginPageProtected(s)){if(r.CrossauthLogger.logger.debug(r.j({msg:"Page is login protected and we don't have credentials"})),this.loginUrl){let a=encodeURIComponent(s.request.url);return new Response(null,{status:302,headers:{location:this.loginUrl+"?next="+a}})}return this.sessionServer.error(401,"Unauthorized")}if(this.sessionServer.isLoginApiProtected(s))return this.sessionServer.error(401,"Unauthorized")}}if(!(n&&n.twofa)&&this.sessionServer.isAdminPageEndpoint(s)&&(!s.locals.user||!U.isAdminFn(s.locals.user)))return this.sessionServer.unauthorizedUrl?new Response(null,{status:302,headers:{location:this.sessionServer.unauthorizedUrl}}):this.sessionServer.error(401,"Unauthorized");if(!(n&&n.twofa)&&this.sessionServer.isAdminApiEndpoint(s)&&(!s.locals.user||!U.isAdminFn(s.locals.user)))return this.sessionServer.error(401,"Unauthorized");if(n!=null&&n.response)return n.response}if(!i&&(this.apiKeyServer&&await this.apiKeyServer.hook({event:s}),this.oAuthClient&&await this.oAuthClient.hook({event:s}),(e=this.oAuthResServer)!=null&&e.hook)){const t=await this.oAuthResServer.hook({event:s});if(t)return t}return s}static isSvelteKitRedirect(s){return typeof s=="object"&&s!=null&&"status"in s&&"location"in s}static isSvelteKitError(s,i){return i?typeof s=="object"&&s!=null&&"status"in s&&"text"in s&&"message"in s&&s.status==i:typeof s=="object"&&s!=null&&"status"in s&&"text"in s&&"message"in s}};U.isAdminFn=ir;let C=U;class V{constructor(s,i){if(this.changePasswordUrl=void 0,this.changeFactor2Url=void 0,this.configureFactor2Url=void 0,this.requestPasswordResetUrl=void 0,this.loginRedirectUrl="/",this.loginUrl="/login",this.signupEndpoint={load:async o=>{var t;return{allowedFactor2:((t=this.sessionServer)==null?void 0:t.allowedFactor2)??[{name:"none",friendlyName:"None"}],...this.baseEndpoint(o)}},actions:{default:async o=>await this.signup(o)}},this.loginEndpoint={load:async o=>({next:o.url.searchParams.get("next")??this.loginRedirectUrl,...this.baseEndpoint(o)}),actions:{login:async o=>{var t;const e=await this.login(o);return(e==null?void 0:e.ok)==!0&&!(e!=null&&e.factor2Required)&&this.sessionServer.redirect(302,((t=e.formData)==null?void 0:t.next)??this.loginRedirectUrl),e&&((e==null?void 0:e.errorCode)==r.ErrorCode.UserNotExist||(e==null?void 0:e.errorCode)==r.ErrorCode.PasswordInvalid)&&(e.error="Username or password is invalid"),e},factor2:async o=>{var t;const e=await this.loginFactor2(o);return(e==null?void 0:e.ok)==!0&&!(e!=null&&e.factor2Required)&&this.sessionServer.redirect(302,((t=e.formData)==null?void 0:t.next)??this.loginRedirectUrl),e}}},this.factor2Endpoint={load:async o=>{const e=await this.requestFactor2(o);return e&&!e.error&&o.url.searchParams.get("error")&&(e.error=o.url.searchParams.get("error")??void 0),e}},this.logoutEndpoint={actions:{default:async o=>await this.logout(o)},load:async o=>({...this.baseEndpoint(o)})},this.changeFactor2Endpoint={actions:{change:async o=>await this.changeFactor2(o),reconfigure:async o=>await this.reconfigureFactor2(o)},load:async o=>{var h;let e=(h=o.locals.user)==null?void 0:h.username;if(!this.isSessionUser(o)||!o.locals.user){const d=await this.sessionServer.getSessionData(o,"factor2change");d!=null&&d.username||this.isSessionUser(o)||(this.sessionServer.unauthorizedUrl&&this.sessionServer.redirect(302,this.sessionServer.unauthorizedUrl),this.sessionServer.error(401,"Unauthorized")),e=d==null?void 0:d.username}let t=this.sessionServer.allowedFactor2??[{name:"none",friendlyName:"None",configurable:!1}],n={},a=o.url.searchParams.get("required"),c;a&&(a=a.toLowerCase(),c=a=="true"||a=="1",c==!0&&(n.required=!0));let l=o.url.searchParams.get("next");return l&&(n.next=l),{allowedFactor2:t,...n,username:e,...this.baseEndpoint(o)}}},this.changePasswordEndpoint={actions:{default:async o=>await this.changePassword(o)},load:async o=>{let e={},t=o.url.searchParams.get("required"),n,a=o.locals.user!=null;if(!a){const l=await this.sessionServer.getSessionData(o,"passwordchange");l!=null&&l.username&&(a=!0)}a||this.sessionServer.redirect(302,this.loginUrl),t&&(t=t.toLowerCase(),n=t=="true"||t=="1",n==!0&&(e.required=!0));let c=o.url.searchParams.get("next");return c&&(e.next=c),{...e,...this.baseEndpoint(o)}}},this.configureFactor2Endpoint={actions:{default:async o=>await this.configureFactor2(o)},load:async o=>({...this.baseEndpoint(o)})},this.deleteUserEndpoint={actions:{default:async o=>await this.deleteUser(o)},load:async o=>({...this.baseEndpoint(o)})},this.resetPasswordEndpoint={actions:{default:async o=>await this.requestPasswordReset(o)},load:async o=>{let e={},t=o.url.searchParams.get("required"),n;return t&&(t=t.toLowerCase(),n=t=="true"||t=="1",n==!0&&(e.required=!0)),{...e,...this.baseEndpoint(o)}}},this.passwordResetTokenEndpoint={actions:{default:async o=>{let e=await this.validatePasswordResetToken(o);if(!(e!=null&&e.user))throw new r.CrossauthError(r.ErrorCode.InvalidToken,"The password reset token is invalid");if(e.user.factor2!=""&&!o.locals.sessionId&&await this.sessionServer.createAnonymousSession(o,{user:{username:e.user.username}}),e!=null&&e.error)return{ok:!1,tokenValidated:!1,error:e==null?void 0:e.error,...this.baseEndpoint(o)};try{return e=await this.resetPassword(o),e}catch(t){const n=r.CrossauthError.asCrossauthError(t);if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{ok:!1,tokenValidated:!1,error:e==null?void 0:e.error,errorCode:n.code,errorCodeName:n.codeName,...this.baseEndpoint(o)}}}},load:async o=>{try{if(o.request.method!="POST"){const e=await this.validatePasswordResetToken(o);if(!(e!=null&&e.user))throw new r.CrossauthError(r.ErrorCode.InvalidToken,"The password reset token is invalid");return e.user.factor2!=""&&!o.locals.sessionId&&await this.sessionServer.createAnonymousSession(o,{user:{username:e.user.username}}),{tokenValidated:(e==null?void 0:e.ok)??!1,error:e==null?void 0:e.error,...this.baseEndpoint(o)}}else return{tokenValidated:!1,...this.baseEndpoint(o)}}catch(e){const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{tokenValidated:!1,error:t.message,errorCode:t.code,errorCodeName:t.codeName,...this.baseEndpoint(o)}}}},this.updateUserEndpoint={actions:{default:async o=>await this.updateUser(o)},load:async o=>({allowedFactor2:this.sessionServer.allowedFactor2??[{name:"none",friendlyName:"None"}],...this.baseEndpoint(o)})},this.verifyEmailTokenEndpoint={load:async o=>{const e=await this.verifyEmail(o);return{...this.baseEndpoint(o),...e}}},this.sessionServer=s,u.setParameter("changePasswordUrl",u.ParamType.String,this,i,"CHANGE_PASSWORD_URL"),u.setParameter("requestPasswordResetUrl",u.ParamType.String,this,i,"REQUEST_PASSWORD_RESET_URL"),u.setParameter("changeFactor2Url",u.ParamType.String,this,i,"CHANGE_FACTOR2_URL"),u.setParameter("configureFactor2Url",u.ParamType.String,this,i,"CONFIGURE_FACTOR2_URL"),u.setParameter("loginRedirectUrl",u.ParamType.JsonArray,this,i,"LOGIN_REDIRECT_URL"),u.setParameter("loginUrl",u.ParamType.JsonArray,this,i,"LOGIN_URL"),i.addToSession&&(this.addToSession=i.addToSession),this.changePasswordUrl&&!this.changePasswordUrl.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"changePasswordUrl must be an absolute path");if(this.requestPasswordResetUrl&&!this.requestPasswordResetUrl.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"requestPasswordResetUrl must be an absolute path");if(this.changeFactor2Url&&!this.changeFactor2Url.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"changeFactor2Url must be an absolute path");if(this.configureFactor2Url&&!this.configureFactor2Url.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"configureFactor2Url must be an absolute path");if(!this.loginUrl.startsWith("/"))throw new r.CrossauthError(r.ErrorCode.Configuration,"loginUrl must be an absolute path")}isSessionUser(s){return s.locals.user!=null&&s.locals.authType=="cookie"}canEditUser(s){return this.isSessionUser(s)||this.sessionServer.editUserScope&&s.locals.scope&&s.locals.scope.includes(this.sessionServer.editUserScope)}async login(s){let i;try{var o=new S;await o.loadData(s),i=o.toObject();const e=o.get("username")??"",t=o.getAsBoolean("persist")??!1;i.next&&i.next.includes("/__data.json")&&(i.next=i.next.substring(0,i.next.indexOf("/__data.json")));let n=i.next??this.loginRedirectUrl;if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"Username field may not be empty");let a=this.addToSession?this.addToSession(s,i):{};if(this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const c=this.sessionServer.getSessionCookieValue(s);let{sessionCookie:l,csrfCookie:h,user:d}=await this.sessionServer.sessionManager.login(e,o.toObject(),a,t);if(r.CrossauthLogger.logger.debug(r.j({msg:"Login: set session cookie "+l.name+" opts "+JSON.stringify(l.options),user:e})),s.cookies.set(l.name,l.value,u.toCookieSerializeOptions(l.options)),r.CrossauthLogger.logger.debug(r.j({msg:"Login: set csrf cookie "+h.name+" opts "+JSON.stringify(l.options),user:e})),this.sessionServer.enableCsrfProtection&&(s.cookies.set(h.name,h.value,u.toCookieSerializeOptions(h.options)),s.locals.csrfToken=await this.sessionServer.sessionManager.createCsrfFormOrHeaderValue(h.value)),c)try{await this.sessionServer.sessionManager.deleteSession(c)}catch(f){r.CrossauthLogger.logger.warn(r.j({msg:"Couldn't delete session ID from database",hashOfSessionId:this.sessionServer.getHashOfSessionId(s)})),r.CrossauthLogger.logger.debug(r.j({err:f}))}if(d.state==r.UserState.passwordChangeNeeded){if(!this.changePasswordUrl)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set changePasswordUrl in session server");this.sessionServer.redirect(302,this.changePasswordUrl+"?required=true&next="+encodeURIComponent("login?next="+n))}else{if(d.state==r.UserState.passwordResetNeeded)throw new r.CrossauthError(r.ErrorCode.PasswordResetNeeded,"Please click on the link we sent you to reset your password");if(d.state==r.UserState.passwordAndFactor2ResetNeeded)throw new r.CrossauthError(r.ErrorCode.PasswordResetNeeded,"Please click on the link we sent you to reset your password");if(this.sessionServer.allowedFactor2.length>0&&d.state==r.UserState.factor2ResetNeeded||!this.sessionServer.allowedFactor2Names.includes(d.factor2?d.factor2:"none")){if(!this.changeFactor2Url)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set changeFactor2Url in session server");this.sessionServer.redirect(302,this.changeFactor2Url+"?required=true&next="+encodeURIComponent("login?next="+n))}else(!d.factor2||d.factor2=="")&&(s.locals.user=d)}return{user:d,formData:i,factor2Required:d.factor2&&d.factor2!="",next:n,ok:!0}}catch(e){if(typeof e=="object"&&e!=null&&"status"in e&&"location"in e)throw e;let t=r.CrossauthError.asCrossauthError(e,"Couldn't log in");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,ok:!1,formData:i,errorCode:t.code,errorCodeName:t.codeName}}}async loginWithUser(s,i,o){const e=o.locals.sessionId,t=new S;await t.loadData(o);let n=this.addToSession?this.addToSession(o,t.toObject()):{},{sessionCookie:a,csrfCookie:c,csrfFormOrHeaderValue:l}=await this.sessionServer.sessionManager.login("",{},n,void 0,s,i);if(r.CrossauthLogger.logger.debug(r.j({msg:"Login: set session cookie "+a.name+" opts "+JSON.stringify(a.options),user:s.username})),o.cookies.set(a.name,a.value,u.toCookieSerializeOptions(a.options)),r.CrossauthLogger.logger.debug(r.j({msg:"Login: set csrf cookie "+c.name+" opts "+JSON.stringify(a.options),user:s.username})),this.sessionServer.enableCsrfProtection&&o.cookies.set(c.name,c.value,u.toCookieSerializeOptions(c.options)),o.locals.user=s,o.locals.csrfToken=l,o.locals.sessionId=this.sessionServer.sessionManager.getSessionId(a.value),e)try{await this.sessionServer.sessionManager.deleteSession(e)}catch(h){r.CrossauthLogger.logger.warn(r.j({msg:"Couldn't delete session ID from database",hashOfSessionId:this.sessionServer.getHashOfSessionId(o)})),r.CrossauthLogger.logger.debug(r.j({err:h}))}return{user:s,ok:!0}}async logout(s){try{if(s.locals.sessionId&&await this.sessionServer.sessionManager.logout(s.locals.sessionId),r.CrossauthLogger.logger.debug(r.j({msg:"Logout: clear cookie "+this.sessionServer.sessionManager.sessionCookieName})),s.cookies.delete(this.sessionServer.sessionManager.sessionCookieName,{path:"/"}),this.sessionServer.enableCsrfProtection&&s.cookies.delete(this.sessionServer.sessionManager.csrfCookieName,{path:"/"}),s.locals.sessionId)try{await this.sessionServer.sessionManager.deleteSession(s.locals.sessionId)}catch(i){r.CrossauthLogger.logger.warn(r.j({msg:"Couldn't delete session ID from database",hashOfSessionId:this.sessionServer.getHashOfSessionId(s)})),r.CrossauthLogger.logger.debug(r.j({err:i}))}if(s.locals.sessionId=void 0,s.locals.user=void 0,this.sessionServer.enableCsrfProtection){s.locals.csrfToken=void 0,s.cookies.delete(this.sessionServer.sessionManager.csrfCookieName,{path:"/"});const{csrfCookie:i,csrfFormOrHeaderValue:o}=await this.sessionServer.sessionManager.createCsrfToken();this.sessionServer.setCsrfCookie(i,s),s.locals.csrfToken=o}return{ok:!0}}catch(i){const o=r.CrossauthError.asCrossauthError(i);return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{ok:!1,error:o.message,errorCode:o.code,errorCodeName:o.codeName}}}async signup(s){let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;await o.loadData(s),i=o.toObject();const e=o.get("username")??"";let t;if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"Username field may not be empty");if(i.factor2||(i.factor2=this.sessionServer.allowedFactor2Names[0]),i.factor2&&!this.sessionServer.allowedFactor2Names.includes(i.factor2??"none"))throw new r.CrossauthError(r.ErrorCode.Forbidden,"Illegal second factor "+i.factor2+" requested");(i.factor2=="none"||i.factor2=="")&&(i.factor2=void 0),t=this.sessionServer.createUserFn(s,i,this.sessionServer.userStorage.userEditableFields,this.sessionServer.userAllowedFactor1);let n=this.sessionServer.authenticators[t.factor1].validateSecrets(i);const a=this.sessionServer.authenticators[t.factor1].secretNames();let c={};for(let f in i)if(f.startsWith("repeat_")){const g=f.replace(/^repeat_/,"");a.includes(g)&&(c[g]=i[f])}Object.keys(c).length===0&&(c=void 0),t.state="active",i.factor2&&i.factor2!="none"?t.state="awaitingtwofactor":this.sessionServer.enableEmailVerification&&(t.state="awaitingemailverification");let h=[...this.sessionServer.validateUserFn(t),...n];if(h.length>0)throw new r.CrossauthError(r.ErrorCode.FormEntry,h);let d=!1;try{const{user:f,secrets:g}=await this.sessionServer.userStorage.getUserByUsername(e);await this.sessionServer.sessionManager.authenticators[t.factor1].authenticateUser(f,g,i)}catch(f){r.CrossauthError.asCrossauthError(f).code==r.ErrorCode.TwoFactorIncomplete&&(d=!0)}if(!i.factor2&&!d)return await this.sessionServer.sessionManager.createUser(t,i,c),this.sessionServer.enableEmailVerification?{emailVerificationRequired:!0,user:t,ok:!0,formData:i}:{...await this.login(s),formData:i};{let f;if(d){if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized);f=(await this.sessionServer.sessionManager.repeatTwoFactorSignup(s.locals.sessionId)).userData}else{const g=await this.sessionServer.createAnonymousSession(s),E=this.sessionServer.sessionManager.getSessionId(g);f=(await this.sessionServer.sessionManager.initiateTwoFactorSignup(t,i,E,c)).userData}try{let g={userData:f,username:e,factor2:i.factor2??"none"};return this.sessionServer.enableCsrfProtection&&(g.csrfToken=s.locals.csrfToken),{factor2Data:g,ok:!0,factor2Required:!0,formData:i}}catch(g){r.CrossauthLogger.logger.error(r.j({err:g}));try{this.sessionServer.sessionManager.deleteUserByUsername(e)}catch(E){r.CrossauthLogger.logger.error(r.j({err:E}))}}}return{user:t,formData:i,ok:!0}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't sign up");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,ok:!1,formData:i,errorCode:t.code,errorCodeName:t.codeName}}}async verifyEmail(s){var i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");const o=s.params.token;if(!o)throw new r.CrossauthError(r.ErrorCode.InvalidToken,"Invalid email verification token");const e=await this.sessionServer.sessionManager.applyEmailVerificationToken(o);if(await this.loginWithUser(e,!0,s),s.locals.user){const t=await this.sessionServer.userStorage.getUserById((i=s.locals.user)==null?void 0:i.id);s.locals.user=t.user}return{ok:!0,user:e}}catch(o){const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName}}}async configureFactor2(s){let i,o,e="";try{var t=new S;await t.loadData(s),i=t.toObject();const n=await this.sessionServer.getSessionData(s,"2fa");if(n!=null&&n.factor2)e=n==null?void 0:n.factor2;else throw new r.CrossauthError(r.ErrorCode.BadRequest,"Two factor authentication was not started");if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session active while enabling 2FA. Please enable cookies");let a=await this.sessionServer.sessionManager.completeTwoFactorSetup(i,s.locals.sessionId);return this.sessionServer.enableEmailVerification||await this.loginWithUser(a,!0,s),s.locals.user?{ok:!0,user:a,emailVerificationRequired:this.sessionServer.enableEmailVerification}:await this.loginWithUser(a,!0,s)}catch(n){const a=r.CrossauthError.asCrossauthError(n);let c;try{c=(await this.sessionServer.sessionManager.repeatTwoFactorSignup(s.locals.sessionId??"")).userData}catch{}return c?o={userData:c,csrfToken:s.locals.csrfToken,username:c.username??"",factor2:e}:o={userData:{},csrfToken:s.locals.csrfToken,username:"",factor2:e},r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{ok:!1,error:a.message,errorCode:a.code,errorCodeName:a.codeName,formData:i,factor2Data:o,emailVerificationRequired:this.sessionServer.enableEmailVerification}}}async loginFactor2(s){if(s.locals.user)return{user:s.locals.user,ok:!0};let i;try{var o=new S;await o.loadData(s),i=o.toObject();const e=o.getAsBoolean("persist")??!1,t=s.locals.sessionId;if(!t)throw new r.CrossauthError(r.ErrorCode.Unauthorized);if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);let n=this.addToSession?this.addToSession(s,i):{};const{sessionCookie:a,csrfCookie:c,user:l}=await this.sessionServer.sessionManager.completeTwoFactorLogin(i,t,n,e);return r.CrossauthLogger.logger.debug(r.j({msg:"Login: set session cookie "+a.name+" opts "+JSON.stringify(a.options),user:l==null?void 0:l.username})),s.cookies.set(a.name,a.value,u.toCookieSerializeOptions(a.options)),r.CrossauthLogger.logger.debug(r.j({msg:"Login: set csrf cookie "+c.name+" opts "+JSON.stringify(a.options),user:l==null?void 0:l.username})),s.cookies.set(c.name,c.value,u.toCookieSerializeOptions(c.options)),this.sessionServer.enableCsrfProtection&&(s.locals.csrfToken=await this.sessionServer.sessionManager.createCsrfFormOrHeaderValue(c.value)),s.locals.user=l,{user:l,ok:!0,formData:i}}catch(e){const t=r.CrossauthError.asCrossauthError(e);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:t.message,errorCode:t.code,errorCodeName:t.codeName,formData:i}}}async requestPasswordReset(s){let i;try{var o=new S;await o.loadData(s),i=o.toObject();const e=o.get("email")??"";if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"Email field may not be empty");if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!this.sessionServer.enablePasswordReset)throw new r.CrossauthError(r.ErrorCode.Configuration,"Password reset not enabled");return await this.sessionServer.sessionManager.requestPasswordReset(e),{formData:i,ok:!0}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't log in");return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{error:t.message,errorCode:t.code,errorCodeName:t.codeName,ok:!1,formData:i}}}async validatePasswordResetToken(s){r.CrossauthLogger.logger.debug(r.j({msg:"validatePasswordResetToken "+s.request.method}));try{const i=s.params.token;if(!i)throw new r.CrossauthError(r.ErrorCode.InvalidToken,"Invalid email verification token");return{ok:!0,user:await this.sessionServer.sessionManager.userForPasswordResetToken(i),formData:{token:i}}}catch(i){const o=r.CrossauthError.asCrossauthError(i);return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{ok:!1,error:o.message,errorCode:o.code,errorCodeName:o.codeName}}}async resetPassword(s){r.CrossauthLogger.logger.debug(r.j({msg:"resetPassword"}));let i;try{var o=new S;if(await o.loadData(s),i=o.toObject(),this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!this.sessionServer.enablePasswordReset)throw new r.CrossauthError(r.ErrorCode.Configuration,"Password reset not enabled");const e=s.params.token??"";if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"No token provided");const t=await this.sessionServer.sessionManager.userForPasswordResetToken(e),n=this.sessionServer.authenticators[t.factor1],a=n.secretNames();let c={},l={};for(let f in i)if(f.startsWith("new_")){const g=f.replace(/^new_/,"");a.includes(g)&&(c[g]=i[f])}else if(f.startsWith("repeat_")){const g=f.replace(/^repeat_/,"");a.includes(g)&&(l[g]=i[f])}if(Object.keys(l).length===0&&(l=void 0),n.validateSecrets(c).length>0)throw new r.CrossauthError(r.ErrorCode.PasswordFormat);const d=await this.sessionServer.sessionManager.resetSecret(e,1,c,l);if(d.state==r.UserState.active)return await this.loginWithUser(d,!0,s);{if(!this.changeFactor2Url)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set changeFactor2Url in session server");const f=this.sessionServer.getSessionCookieValue(s),g=this.sessionServer.sessionManager.getSessionId(f??"");throw await this.sessionServer.sessionManager.updateSessionData(g,"factor2change",{username:t.username}),this.sessionServer.redirect(302,this.changeFactor2Url+"?required=true")}}catch(e){if(C.isSvelteKitRedirect(e))throw e;let t=r.CrossauthError.asCrossauthError(e,"Couldn't log in");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,errorCode:t.code,errorCodeName:t.codeName,ok:!1,formData:i}}}async requestFactor2(s){try{if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session cookie present");const i=this.sessionServer.getSessionCookieValue(s),o=this.sessionServer.sessionManager.getSessionId(i??""),e=await this.sessionServer.sessionManager.dataForSessionId(o);if(!(e!=null&&e.pre2fa))throw new r.CrossauthError(r.ErrorCode.Unauthorized,"2FA not initiated");return{ok:!0,csrfToken:s.locals.csrfToken,action:e.pre2fa.url,factor2:e.pre2fa.factor2}}catch(i){let o=r.CrossauthError.asCrossauthError(i,"2FA failed");return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{error:o.message,errorCode:o.code,errorCodeName:o.codeName,ok:!1}}}async changePassword(s){r.CrossauthLogger.logger.debug(r.j({msg:"changePassword"}));let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;await o.loadData(s),i=o.toObject();let e,t=!1;if(!this.isSessionUser(s)||!s.locals.user){const g=await this.sessionServer.getSessionData(s,"passwordchange");if(g!=null&&g.username){if(e=(await this.sessionServer.userStorage.getUserByUsername(g==null?void 0:g.username,{skipActiveCheck:!0,skipEmailVerifiedCheck:!0})).user,t=!0,this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf)}else throw new r.CrossauthError(r.ErrorCode.Unauthorized)}else if(this.canEditUser(s)){if(this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);e=s.locals.user}else throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);const n=this.sessionServer.authenticators[e.factor1],a=n.secretNames();let c={},l={},h={};for(let g in i)if(g.startsWith("new_")){const E=g.replace(/^new_/,"");a.includes(E)&&(l[E]=i[g])}else if(g.startsWith("old_")){const E=g.replace(/^old_/,"");a.includes(E)&&(c[E]=i[g])}else if(g.startsWith("repeat_")){const E=g.replace(/^repeat_/,"");a.includes(E)&&(h[E]=i[g])}if(Object.keys(h).length===0&&(h=void 0),n.validateSecrets(l).length>0)throw new r.CrossauthError(r.ErrorCode.PasswordFormat);const f=e.state;try{t&&(e.state="active",await this.sessionServer.userStorage.updateUser({id:e.id,state:e.state})),await this.sessionServer.sessionManager.changeSecrets(e.username,1,l,h,c)}catch(g){const E=r.CrossauthError.asCrossauthError(g);if(r.CrossauthLogger.logger.debug(r.j({err:g})),t)try{await this.sessionServer.userStorage.updateUser({id:e.id,state:f})}catch(w){r.CrossauthLogger.logger.debug(r.j({err:w}))}throw E}return t?await this.loginWithUser(e,!1,s):{ok:!0,formData:i}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't change password");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,ok:!1,errorCode:t.code,errorCodeName:t.codeName,formData:i}}}async deleteUser(s){r.CrossauthLogger.logger.debug(r.j({msg:"deleteUser"}));try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");if(this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!s.locals.user)throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);return await this.sessionServer.userStorage.deleteUserById(s.locals.user.id),s.cookies.delete(this.sessionServer.sessionManager.sessionCookieName,{path:"/"}),s.locals.sessionId=void 0,s.locals.user=void 0,{ok:!0}}catch(i){let o=r.CrossauthError.asCrossauthError(i,"Couldn't delete account");return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{error:o.message,errorCode:o.code,errorCodeName:o.codeName,ok:!1}}}async updateUser(s){r.CrossauthLogger.logger.debug(r.j({msg:"updateUser"}));let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;if(await o.loadData(s),i=o.toObject(),this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(!s.locals.user)throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);let e={id:s.locals.user.id,username:s.locals.user.username,state:"active"};e=this.sessionServer.updateUserFn(e,s,i,this.sessionServer.userStorage.userEditableFields);let t=this.sessionServer.validateUserFn(e);if(t.length>0)throw new r.CrossauthError(r.ErrorCode.FormEntry,t);let{emailVerificationTokenSent:n}=await this.sessionServer.sessionManager.updateUser(s.locals.user,e);if(!n){const a=await this.sessionServer.userStorage.getUserById(s.locals.user.id);s.locals.user=a.user}return{ok:!0,formData:i,emailVerificationNeeded:n}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't update account");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,errorCode:t.code,errorCodeName:t.codeName,ok:!1,formData:i,emailVerificationNeeded:!1}}}async changeFactor2(s){var e;r.CrossauthLogger.logger.debug(r.j({msg:"updateUser"}));let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;if(await o.loadData(s),i=o.toObject(),this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);let t=(e=s.locals.user)==null?void 0:e.username;if(!this.isSessionUser(s)||!s.locals.user){const l=await this.sessionServer.getSessionData(s,"factor2change");l!=null&&l.username||this.isSessionUser(s)||(this.sessionServer.unauthorizedUrl&&this.sessionServer.redirect(302,this.sessionServer.unauthorizedUrl),this.sessionServer.error(401,"Unauthorized")),t=l==null?void 0:l.username}let n=s.locals.user;if(!n&&t&&(n=(await this.sessionServer.userStorage.getUserByUsername(t,{skipActiveCheck:!0,skipEmailVerifiedCheck:!0})).user),!n)throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized);let a=i.factor2;if(i.factor2&&!this.sessionServer.allowedFactor2Names.includes(i.factor2))throw new r.CrossauthError(r.ErrorCode.Forbidden,"Illegal second factor "+i.factor2+" requested");if((i.factor2=="none"||i.factor2=="")&&(a=void 0,!s.locals.user))return await this.loginWithUser(n,!0,s);const c=await this.sessionServer.sessionManager.initiateTwoFactorSetup(n,a,s.locals.sessionId);return a?{ok:!0,formData:i,factor2Data:{username:n.username,factor2:a??"",userData:c,csrfToken:s.locals.csrfToken}}:{ok:!0,formData:i}}catch(t){let n=r.CrossauthError.asCrossauthError(t,"Couldn't update account");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1,formData:i}}}async reconfigureFactor2(s){var e;r.CrossauthLogger.logger.debug(r.j({msg:"updateUser"}));let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;if(await o.loadData(s),i=o.toObject(),this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);let t=(e=s.locals.user)==null?void 0:e.username;if(!this.isSessionUser(s)||!s.locals.user){const h=await this.sessionServer.getSessionData(s,"factor2change");h!=null&&h.username||this.isSessionUser(s)||(this.sessionServer.unauthorizedUrl&&this.sessionServer.redirect(302,this.sessionServer.unauthorizedUrl),this.sessionServer.error(401,"Unauthorized")),t=h==null?void 0:h.username}let n=s.locals.user;if(!n&&t&&(n=(await this.sessionServer.userStorage.getUserByUsername(t,{skipActiveCheck:!0,skipEmailVerifiedCheck:!0})).user),!n)throw new r.CrossauthError(r.ErrorCode.InsufficientPriviledges);if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized);if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized);let a=n.factor2;const c=this.sessionServer.authenticators[a];if(!c||c.secretNames().length==0)throw new r.CrossauthError(r.ErrorCode.BadRequest,"Selected second factor does not have configuration");const l=await this.sessionServer.sessionManager.initiateTwoFactorSetup(n,a,s.locals.sessionId);return{ok:!0,formData:i,factor2Data:{username:n.username,factor2:n.factor2??"",userData:l,csrfToken:s.locals.csrfToken}}}catch(t){let n=r.CrossauthError.asCrossauthError(t,"Couldn't update account");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1,formData:i}}}baseEndpoint(s){return{user:s.locals.user,csrfToken:s.locals.csrfToken}}}async function ar(p,s,i=0,o=10){let e=[];if(i>0)return[];try{const{user:t}=await s.getUserByUsername(p);e.push(t)}catch(t){const n=r.CrossauthError.asCrossauthError(t);if(n.code!=r.ErrorCode.UserNotExist)throw r.CrossauthLogger.logger.debug(r.j({err:n})),n;try{const{user:a}=await s.getUserByEmail(p);e.push(a)}catch(a){const c=r.CrossauthError.asCrossauthError(a);if(c.code!=r.ErrorCode.UserNotExist)throw r.CrossauthLogger.logger.debug(r.j({err:c})),n}}return e}class W{constructor(s,i){this.userSearchFn=ar,this.searchUsersEndpoint={load:async o=>{(!o.locals.user||!C.isAdminFn(o.locals.user))&&this.sessionServer.error(o,401);const e=await this.searchUsers(o);return{...this.baseEndpoint(o),...e}}},this.updateUserEndpoint={actions:{default:async o=>{var n,a,c;const e=await this.getUserFromParam(o);return e.exception||!e.user?{ok:!1,error:((n=e.exception)==null?void 0:n.message)??"Couldn't get user",errorCode:(a=e.exception)==null?void 0:a.code,errorCodeName:(c=e.exception)==null?void 0:c.codeName}:await this.updateUser(e.user,o)}},load:async o=>{(!o.locals.user||!C.isAdminFn(o.locals.user))&&this.sessionServer.error(o,401);let e=this.sessionServer.allowedFactor2??[{name:"none",friendlyName:"None"}];const t=await this.getUserFromParam(o);return t.exception||!t.user?{allowedFactor2:e,editUser:t.user,...this.baseEndpoint(o)}:{allowedFactor2:e,editUser:t.user,...this.baseEndpoint(o)}}},this.changePasswordEndpoint={actions:{default:async o=>{var n,a,c;const e=await this.getUserFromParam(o);return e.exception||!e.user?{ok:!1,error:((n=e.exception)==null?void 0:n.message)??"Couldn't get user",errorCode:(a=e.exception)==null?void 0:a.code,errorCodeName:(c=e.exception)==null?void 0:c.codeName}:await this.changePassword(e.user,o)}},load:async o=>{(!o.locals.user||!C.isAdminFn(o.locals.user))&&this.sessionServer.error(o,401);const e=await this.getUserFromParam(o);if(e.exception||!e.user)return{editUser:e.user,...this.baseEndpoint(o)};let t={},n=o.url.searchParams.get("next");return n&&(t.next=n),{...t,editUser:e.user,...this.baseEndpoint(o)}}},this.createUserEndpoint={load:async o=>{var t;return(!o.locals.user||!C.isAdminFn(o.locals.user))&&this.sessionServer.error(o,401),{allowedFactor2:((t=this.sessionServer)==null?void 0:t.allowedFactor2)??[{name:"none",friendlyName:"None"}],...this.baseEndpoint(o)}},actions:{default:async o=>await this.createUser(o)}},this.deleteUserEndpoint={actions:{default:async o=>await this.deleteUser(o)},load:async o=>{var t,n,a;const e=await this.getUserFromParam(o);return e.exception||!e.user?{error:"User doesn't exist",errorCode:(t=e.exception)==null?void 0:t.code,errorCodeName:(n=e.exception)==null?void 0:n.codeName,...this.baseEndpoint(o)}:{username:(a=e.user)==null?void 0:a.username,...this.baseEndpoint(o)}}},this.sessionServer=s,i.userSearchFn&&(this.userSearchFn=i.userSearchFn)}isSessionUser(s){return s.locals.user!=null&&s.locals.authType=="cookie"}async searchUsers(s,i,o,e){try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");(!s.locals.user||!C.isAdminFn(s.locals.user))&&this.sessionServer.error(401);let t=[],n=[],a=[];if(!o)try{const l=s.url.searchParams.get("skip");l&&(o=parseInt(l))}catch(l){r.CrossauthLogger.logger.warn(r.j({cerr:l,msg:"skip parameter is not an integer"}))}if(o||(o=0),!e)try{const l=s.url.searchParams.get("take");l&&(e=parseInt(l))}catch(l){r.CrossauthLogger.logger.warn(r.j({cerr:l,msg:"take parameter is not an integer"}))}e||(e=10);const c=s.url.searchParams.get("search");return!i&&c!=null&&c!=""&&(i=c),i||(i=""),i.length==0&&(i=void 0),i?(t=await this.userSearchFn(i,this.sessionServer.userStorage,o,e),o>0&&(n=await this.userSearchFn(i,this.sessionServer.userStorage,o-1,1))):(t=await this.sessionServer.userStorage.getUsers(o,e),t.length==e&&(a=await this.sessionServer.userStorage.getUsers(o+e,1))),{ok:!0,users:t,skip:o,take:e,hasPrevious:n.length>0,hasNext:a.length>0,search:i}}catch(t){const n=r.CrossauthError.asCrossauthError(t);return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{ok:!1,error:n.message,errorCode:n.code,errorCodeName:n.codeName,hasPrevious:!1,hasNext:!1,skip:o??0,take:e??10,search:i}}}async updateUser(s,i){let o;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var e=new S;if(await e.loadData(i),o=e.toObject(),(!i.locals.user||!C.isAdminFn(i.locals.user))&&this.sessionServer.error(401),this.isSessionUser(i)&&this.sessionServer.enableCsrfProtection&&!i.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const t=s.factor2,n=s.state;s.state=o.state??"active",s=this.sessionServer.updateUserFn(s,i,o,{...this.sessionServer.userStorage.userEditableFields,...this.sessionServer.userStorage.adminEditableFields});const a=s.factor2&&s.factor2!="none"&&s.factor2!=t;if(a&&!(s.state==n||s.state=="factor2ResetNeeded"))throw new r.CrossauthError(r.ErrorCode.BadRequest,"Cannot change both factor2 and state at the same time");a&&(s.state=r.UserState.factor2ResetNeeded,r.CrossauthLogger.logger.warn(r.j({msg:`Setting state for user to ${r.UserState.factor2ResetNeeded}`,username:s.username})));let c=this.sessionServer.validateUserFn(s);if(c.length>0)throw new r.CrossauthError(r.ErrorCode.FormEntry,c);const l=await this.sessionServer.sessionManager.updateUser(s,s,!0,!0);let h;return l.emailVerificationTokenSent?h="An email verification token has been sent to the user":l.passwordResetTokenSent&&(h="A password reset token has been sent to the user"),{ok:!0,formData:o,info:h}}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t,401))throw t;let n=r.CrossauthError.asCrossauthError(t,"Couldn't log in");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1,formData:o}}}async changePassword(s,i){r.CrossauthLogger.logger.debug(r.j({msg:"changePassword"}));let o;try{var e=new S;if(await e.loadData(i),o=e.toObject(),(!i.locals.user||!C.isAdminFn(i.locals.user))&&this.sessionServer.error(401),this.isSessionUser(i)&&this.sessionServer.enableCsrfProtection&&!i.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const t=this.sessionServer.authenticators[s.factor1],n=t.secretNames();let a={},c={},l={};for(let d in o)if(d.startsWith("new_")){const f=d.replace(/^new_/,"");n.includes(f)&&(c[f]=o[d])}else if(d.startsWith("old_")){const f=d.replace(/^old_/,"");n.includes(f)&&(a[f]=o[d])}else if(d.startsWith("repeat_")){const f=d.replace(/^repeat_/,"");n.includes(f)&&(l[f]=o[d])}if(Object.keys(l).length===0&&(l=void 0),Object.keys(a).length===0&&(a=void 0),t.validateSecrets(c).length>0)throw new r.CrossauthError(r.ErrorCode.PasswordFormat);try{await this.sessionServer.sessionManager.changeSecrets(s.username,1,c,l,a)}catch(d){const f=r.CrossauthError.asCrossauthError(d);throw r.CrossauthLogger.logger.debug(r.j({err:d})),f}return{ok:!0,formData:o}}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t,401))throw t;let n=r.CrossauthError.asCrossauthError(t,"Couldn't change password");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1,formData:o}}}async createUser(s){let i;try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");var o=new S;await o.loadData(s),i=o.toObject();const e=o.get("username")??"";let t;if((!s.locals.user||!C.isAdminFn(s.locals.user))&&this.sessionServer.error(401),this.isSessionUser(s)&&this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);if(e=="")throw new r.CrossauthError(r.ErrorCode.InvalidUsername,"Username field may not be empty");if(i.factor2||(i.factor2=this.sessionServer.allowedFactor2Names[0]),i.factor2&&!this.sessionServer.allowedFactor2Names.includes(i.factor2??"none"))throw new r.CrossauthError(r.ErrorCode.Forbidden,"Illegal second factor "+i.factor2+" requested");(i.factor2=="none"||i.factor2=="")&&(i.factor2=void 0),t=this.sessionServer.createUserFn(s,i,{...this.sessionServer.userStorage.userEditableFields,...this.sessionServer.userStorage.adminEditableFields},this.sessionServer.adminAllowedFactor1);const n=this.sessionServer.authenticators[t.factor1].secretNames();let a=!0;for(let g of n)!i[g]&&!i["repeat_"+g]&&(a=!1);let c=[],l={};if(a){c=this.sessionServer.authenticators[t.factor1].validateSecrets(i);for(let g in i)if(g.startsWith("repeat_")){const E=g.replace(/^repeat_/,"");n.includes(E)&&(l[E]=i[g])}Object.keys(l).length===0&&(l=void 0)}a?i.factor2!=null&&(t.state=r.UserState.factor2ResetNeeded):i.factor2==null?t.state=r.UserState.passwordResetNeeded:t.state=r.UserState.passwordAndFactor2ResetNeeded;let d=[...this.sessionServer.validateUserFn(t),...c];if(d.length>0)throw new r.CrossauthError(r.ErrorCode.FormEntry,d);const f=await this.sessionServer.sessionManager.createUser(t,i,l,!0,!a);if(!a){let g=i.username;if("user_email"in i&&(g=i.user_email),u.TokenEmailer.validateEmail(g),!g)throw new r.CrossauthError(r.ErrorCode.FormEntry,"No password given but no email address found either");await this.sessionServer.sessionManager.requestPasswordReset(g)}return{ok:!0,user:f,formData:i}}catch(e){let t=r.CrossauthError.asCrossauthError(e,"Couldn't create user");return r.CrossauthLogger.logger.debug(r.j({err:t})),r.CrossauthLogger.logger.error(r.j({cerr:t})),{error:t.message,errorCode:t.code,errorCodeName:t.codeName,ok:!1,formData:i}}}async deleteUser(s){if(r.CrossauthLogger.logger.debug(r.j({msg:"deleteUser"})),!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");try{const i=s.params.id;if(!i)throw new r.CrossauthError(r.ErrorCode.BadRequest,"User ID is undefined");if(this.sessionServer.enableCsrfProtection&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);return(!s.locals.user||!C.isAdminFn(s.locals.user))&&this.sessionServer.error(401),await this.sessionServer.userStorage.deleteUserById(i),{ok:!0}}catch(i){let o=r.CrossauthError.asCrossauthError(i,"Couldn't delete account");return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o})),{error:o.message,errorCode:o.code,errorCodeName:o.codeName,ok:!1}}}baseEndpoint(s){return{user:s.locals.user,csrfToken:s.locals.csrfToken}}async getUserFromParam(s,i="id"){let o=s.params[i];if(!o)return{exception:new r.CrossauthError(r.ErrorCode.BadRequest,"Must give user id")};try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");return{user:(await this.sessionServer.userStorage.getUserById(o,{skipEmailVerifiedCheck:!0,skipActiveCheck:!0})).user}}catch(e){return{exception:r.CrossauthError.asCrossauthError(e)}}}}async function J(p,s,i,o,e){let t=[];if(i>0)return[];try{const n=await s.getClientById(p);t.push(n)}catch(n){const a=r.CrossauthError.asCrossauthError(n);if(a.code!=r.ErrorCode.UserNotExist)throw r.CrossauthLogger.logger.debug(r.j({err:a})),a;try{t=await s.getClientByName(p,e)}catch(c){const l=r.CrossauthError.asCrossauthError(c);if(l.code!=r.ErrorCode.UserNotExist)throw r.CrossauthLogger.logger.debug(r.j({err:l})),a}}return t}class O{constructor(s,i){this.loginUrl="/login",this.clientSearchFn=J,this.validFlows=["all"],this.sessionServer=s,u.setParameter("loginUrl",u.ParamType.JsonArray,this,i,"LOGIN_URL"),i.clientSearchFn&&(this.clientSearchFn=i.clientSearchFn),this.redirect=i.redirect??m.redirect,this.error=i.error??m.error,u.setParameter("validFlows",u.ParamType.JsonArray,this,i,"OAUTH_validFlows"),this.validFlows.length==1&&this.validFlows[0]==r.OAuthFlows.All&&(this.validFlows=r.OAuthFlows.allFlows()),this.valid_flowNames=r.OAuthFlows.flowNames(this.validFlows),i.clientStorage&&(this.clientManager=new u.OAuthClientManager(i)),this.clientStorage=i.clientStorage}async searchClients_internal(s,i,o,e,t){try{if(!this.sessionServer.userStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide user storage to use this function");if(!this.sessionServer.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must provide client storage to use this function");if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));let n=[],a=[],c=[];if(!o)try{const h=s.url.searchParams.get("skip");h&&(o=parseInt(h))}catch(h){r.CrossauthLogger.logger.warn(r.j({cerr:h,msg:"skip parameter is not an integer"}))}if(o||(o=0),!e)try{const h=s.url.searchParams.get("take");h&&(e=parseInt(h))}catch(h){r.CrossauthLogger.logger.warn(r.j({cerr:h,msg:"take parameter is not an integer"}))}e||(e=10);const l=s.url.searchParams.get("search");return!i&&l!=null&&l!=""&&(i=l),i||(i=""),i.length==0&&(i=void 0),i?(n=await this.clientSearchFn(i,this.sessionServer.clientStorage,o,e),o>0&&(a=await this.clientSearchFn(i,this.sessionServer.clientStorage,o-1,1,t))):(n=await this.sessionServer.clientStorage.getClients(o,e,t),n.length==e&&(c=await this.sessionServer.clientStorage.getClients(o+e,1,t))),{ok:!0,clients:n,skip:o,take:e,hasPrevious:a.length>0,hasNext:c.length>0,search:i,clientUserId:t}}catch(n){if(C.isSvelteKitRedirect(n)||C.isSvelteKitRedirect(n))throw n;const a=r.CrossauthError.asCrossauthError(n);return r.CrossauthLogger.logger.debug(r.j({err:a})),r.CrossauthLogger.logger.error(r.j({cerr:a})),{ok:!1,error:a.message,errorCode:a.code,errorCodeName:a.codeName,hasPrevious:!1,hasNext:!1,skip:o??0,take:e??10,search:i,clientUserId:t}}}async loadClient_internal(s){var o,e,t;const i=s.params.client_id;try{if(!i)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID specified");if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");const n=await this.clientStorage.getClientById(i),a=n.userid==null?void 0:await((e=(o=this.sessionServer)==null?void 0:o.userStorage)==null?void 0:e.getUserById(n.userid)),c=(t=a==null?void 0:a.user)==null?void 0:t.username;return{ok:!0,client:n,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames,client_id:i,clientUsername:c}}catch(n){let a=r.CrossauthError.asCrossauthError(n,"Couldn't load client");return r.CrossauthLogger.logger.debug(r.j({err:a})),r.CrossauthLogger.logger.error(r.j({cerr:a})),{error:a.message,errorCode:a.code,errorCodeName:a.codeName,ok:!1,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames,client_id:i}}}async updateClient_internal(s,i){var t,n;let o;try{const a=s.params.client_id;if(!a)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");var e=new S;if(await e.loadData(s),o=e.toObject(),this.sessionServer.enableCsrfProtection&&s.locals.authType=="cookie"&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const c=!o.redirect_uri||o.redirect_uri.trim().length==0?[]:o.redirect_uri.trim().split(/[, ][ \t\n]*/);let l=[];for(let w of c)try{u.OAuthClientManager.validateUri(w)}catch(k){r.CrossauthLogger.logger.error(r.j({err:k})),l.push("["+w+"]")}if(l.length>0)throw new r.CrossauthError(r.ErrorCode.BadRequest,"The following redirect URIs are invalid: "+l.join(" "));let h=[];for(let w of this.validFlows)w in o&&h.push(w);const d={};if(d.client_name=o.client_name,d.confidential=e.getAsBoolean("confidential")??!1,d.valid_flow=h,d.redirect_uri=c,i){let w=o.userid??void 0;if(w&&((t=this.sessionServer)!=null&&t.userStorage)){const{user:k}=await((n=this.sessionServer)==null?void 0:n.userStorage.getUserById(w));w=k.id}d.userid=o.userid?Number(o.userid):null}const f=e.getAsBoolean("resetSecret");if(!this.clientManager)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot call this endpoint as you did not provide a clientStorage");const{client:g,newSecret:E}=await this.clientManager.updateClient(a,d,f);return{ok:!0,client:g,formData:o,plaintextSecret:E&&g.client_secret?g.client_secret:void 0}}catch(a){if(C.isSvelteKitRedirect(a)||C.isSvelteKitError(a))throw a;let c=r.CrossauthError.asCrossauthError(a,"Couldn't update client");return r.CrossauthLogger.logger.debug(r.j({err:c})),r.CrossauthLogger.logger.error(r.j({cerr:c})),{error:c.message,errorCode:c.code,errorCodeName:c.codeName,ok:!1,formData:o}}}async emptyClient_internal(s,i){var e,t,n,a,c,l,h;try{var o=new S;await o.loadData(s);let d;if(i){const E=s.url.searchParams.get("userid");if(E&&((e=this.sessionServer)!=null&&e.userStorage)){const{user:k}=await((t=this.sessionServer)==null?void 0:t.userStorage.getUserById(E));d=k.id}const w=o.get("userid");if(w&&((n=this.sessionServer)!=null&&n.userStorage)){const{user:k}=await((a=this.sessionServer)==null?void 0:a.userStorage.getUserById(w));d=k.id}}else{if(!s.locals.user)throw new r.CrossauthError(r.ErrorCode.Unauthorized);d=s.locals.user.id}if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");const f=d==null?void 0:await((l=(c=this.sessionServer)==null?void 0:c.userStorage)==null?void 0:l.getUserById(d)),g=(h=f==null?void 0:f.user)==null?void 0:h.username;return{ok:!0,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames,clientUserId:d,clientUsername:g}}catch(d){let f=r.CrossauthError.asCrossauthError(d,"Couldn't initialize new client");return r.CrossauthLogger.logger.debug(r.j({err:f})),r.CrossauthLogger.logger.error(r.j({cerr:f})),{error:f.message,errorCode:f.code,errorCodeName:f.codeName,ok:!1,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames}}}async createClient_internal(s,i){var t,n,a,c;let o;try{var e=new S;await e.loadData(s),o=e.toObject();let l;if(i){const w=e.get("userid");if(w&&((t=this.sessionServer)!=null&&t.userStorage)){const{user:k}=await((n=this.sessionServer)==null?void 0:n.userStorage.getUserById(w));l=k.id}}else{if(!s.locals.user)throw new r.CrossauthError(r.ErrorCode.Unauthorized);l=s.locals.user.id}if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");if(l&&await((c=(a=this.sessionServer)==null?void 0:a.userStorage)==null?void 0:c.getUserById(l)),this.sessionServer.enableCsrfProtection&&s.locals.authType=="cookie"&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const h=!o.redirect_uri||o.redirect_uri.trim().length==0?[]:o.redirect_uri.trim().split(/[, ][ \t\n]*/);let d=[];for(let w of h)try{u.OAuthClientManager.validateUri(w)}catch(k){r.CrossauthLogger.logger.error(r.j({err:k})),d.push("["+w+"]")}if(d.length>0)throw new r.CrossauthError(r.ErrorCode.BadRequest,"The following redirect URIs are invalid: "+d.join(" "));let f=[];for(let w of this.validFlows)w in o&&f.push(w);const g={};if(g.client_name=o.client_name,g.confidential=e.getAsBoolean("confidential"),g.valid_flow=f,g.redirect_uri=h,i&&(g.userid=o.userid?Number(o.userid):null),!this.clientManager)throw new r.CrossauthError(r.ErrorCode.Configuration,"Cannot call this endpoint as you did not provide a clientStorage");return{ok:!0,client:await this.clientManager.createClient(o.client_name,h,f,e.getAsBoolean("confidential")??!1,l),formData:o}}catch(l){if(C.isSvelteKitRedirect(l)||C.isSvelteKitError(l))throw l;let h=r.CrossauthError.asCrossauthError(l,"Couldn't create client");return r.CrossauthLogger.logger.debug(r.j({err:h})),r.CrossauthLogger.logger.error(r.j({cerr:h})),{error:h.message,errorCode:h.code,errorCodeName:h.codeName,ok:!1,formData:o}}}async loadDeleteClient_internal(s){var o,e,t;const i=s.params.client_id;try{if(!i)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID specified");if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");const n=await this.clientStorage.getClientById(i),a=n.userid==null?void 0:await((e=(o=this.sessionServer)==null?void 0:o.userStorage)==null?void 0:e.getUserById(n.userid)),c=(t=a==null?void 0:a.user)==null?void 0:t.username;return{ok:!0,client:n,client_id:i,clientUsername:c}}catch(n){let a=r.CrossauthError.asCrossauthError(n,"Couldn't load client");return r.CrossauthLogger.logger.debug(r.j({err:a})),r.CrossauthLogger.logger.error(r.j({cerr:a})),{error:a.message,errorCode:a.code,errorCodeName:a.codeName,ok:!1,client_id:i}}}async deleteClient_internal(s,i){var o,e;try{if(this.sessionServer.enableCsrfProtection&&s.locals.authType=="cookie"&&!s.locals.csrfToken)throw new r.CrossauthError(r.ErrorCode.InvalidCsrf);const t=s.params.client_id;if(!t)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");if(!this.clientStorage)throw new r.CrossauthError(r.ErrorCode.Configuration,"No client storage specified");const n=await((o=this.clientStorage)==null?void 0:o.getClientById(t));if(!i&&n.userid!=((e=s.locals.user)==null?void 0:e.id))throw this.error(401,"Unauthorized");return await this.clientStorage.deleteClient(t),{ok:!0}}catch(t){if(C.isSvelteKitRedirect(t)||C.isSvelteKitError(t))throw t;let n=r.CrossauthError.asCrossauthError(t,"Couldn't delete client");return r.CrossauthLogger.logger.debug(r.j({err:n})),r.CrossauthLogger.logger.error(r.j({cerr:n})),{error:n.message,errorCode:n.code,errorCodeName:n.codeName,ok:!1}}}baseEndpoint(s){return{user:s.locals.user,csrfToken:s.locals.csrfToken}}}class G extends O{constructor(s,i){super(s,i),this.searchClientsEndpoint={load:async o=>{const e=await this.searchClients(o);return{...this.baseEndpoint(o),...e}}},this.updateClientEndpoint={load:async o=>{const e=await this.loadClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.updateClient(o)}},this.createClientEndpoint={load:async o=>{const e=await this.emptyClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.createClient(o)}},this.deleteClientEndpoint={load:async o=>{const e=await this.loadDeleteClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.deleteClient(o)}},this.sessionServer=s,u.setParameter("loginUrl",u.ParamType.JsonArray,this,i,"LOGIN_URL"),i.clientSearchFn&&(this.clientSearchFn=i.clientSearchFn),this.redirect=i.redirect,this.error=i.error}async searchClients(s,i,o,e){var t;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));return this.searchClients_internal(s,i,o,e,(t=s.locals.user)==null?void 0:t.id)}async loadClient(s){var i;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));try{const o=s.params.client_id;if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");const e=await((i=this.clientStorage)==null?void 0:i.getClientById(o));if((e==null?void 0:e.userid)!=s.locals.user.id)return this.error(401,"Access denied")}catch(o){if(C.isSvelteKitRedirect(o)||C.isSvelteKitError(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName,validFlows:this.validFlows,valid_flowNames:this.valid_flowNames}}return this.loadClient_internal(s)}async updateClient(s){var i;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));try{const o=s.params.client_id;if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");const e=await((i=this.clientStorage)==null?void 0:i.getClientById(o));if((e==null?void 0:e.userid)!=s.locals.user.id)return this.error(401,"Access denied")}catch(o){if(C.isSvelteKitRedirect(o)||C.isSvelteKitError(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName}}return this.updateClient_internal(s,!1)}async loadDeleteClient(s){var i;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));try{const o=s.params.client_id;if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");const e=await((i=this.clientStorage)==null?void 0:i.getClientById(o));if((e==null?void 0:e.userid)!=s.locals.user.id)return this.error(401,"Access denied")}catch(o){if(C.isSvelteKitRedirect(o)||C.isSvelteKitError(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName}}return this.loadDeleteClient_internal(s)}async deleteClient(s){var i;if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));try{const o=s.params.client_id;if(!o)throw new r.CrossauthError(r.ErrorCode.BadRequest,"No client ID given");const e=await((i=this.clientStorage)==null?void 0:i.getClientById(o));if((e==null?void 0:e.userid)!=s.locals.user.id)return this.error(401,"Access denied")}catch(o){if(C.isSvelteKitRedirect(o)||C.isSvelteKitError(o))throw o;const e=r.CrossauthError.asCrossauthError(o);return r.CrossauthLogger.logger.debug(r.j({err:e})),r.CrossauthLogger.logger.error(r.j({cerr:e})),{ok:!1,error:e.message,errorCode:e.code,errorCodeName:e.codeName}}return this.deleteClient_internal(s,!1)}async emptyClient(s){if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));return this.emptyClient_internal(s,!1)}async createClient(s){if(!s.locals.user)throw this.redirect(302,this.loginUrl+"?next="+encodeURIComponent(s.request.url));return this.createClient_internal(s,!1)}}class Q extends O{constructor(s,i){super(s,i),this.searchClientsEndpoint={load:async o=>{let e;try{e=o.url.searchParams.get("userid")?Number(o.url.searchParams.get("userid")):void 0}catch{r.CrossauthLogger.logger.warn(r.j({msg:"Invalid userid "+o.url.searchParams.get("userid")}))}const t=await this.searchClients(o,void 0,void 0,void 0,e);return{...this.baseEndpoint(o),...t}}},this.updateClientEndpoint={load:async o=>{const e=await this.loadClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.updateClient(o)}},this.createClientEndpoint={load:async o=>{const e=await this.emptyClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.createClient(o)}},this.deleteClientEndpoint={load:async o=>{const e=await this.loadDeleteClient(o);return{...this.baseEndpoint(o),...e}},actions:{default:async o=>await this.deleteClient(o)}},this.sessionServer=s,u.setParameter("loginUrl",u.ParamType.String,this,i,"LOGIN_URL"),i.clientSearchFn&&(this.clientSearchFn=i.clientSearchFn),this.redirect=i.redirect,this.error=i.error}async searchClients(s,i,o,e,t){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.searchClients_internal(s,i,o,e,t)}async loadClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.loadClient_internal(s)}async updateClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.updateClient_internal(s,!0)}async emptyClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.emptyClient_internal(s,!0)}async createClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.createClient_internal(s,!0)}async loadDeleteClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.loadDeleteClient_internal(s)}async deleteClient(s){if(!s.locals.user||!C.isAdminFn(s.locals.user))throw this.error(401,"Unauthorized");return this.deleteClient_internal(s,!0)}}const L="X-CROSSAUTH-CSRF";function nr(p){let s=[];return p.username==null?s.push("Username must be given"):p.username.length<2?s.push("Username must be at least 2 characters"):p.username.length>254&&s.push("Username must be no longer than 254 characters"),s}function cr(p,s,i,o=["localpassword"]){var a;let t={username:s.username??"",state:"active"};const n=p.locals.user&&C.isAdminFn(p.locals.user);for(let c in s){let l=c.replace(/^user_/,"");if(c.startsWith("user_")&&(n||i.includes(l)))if("type_"+l in s){if(s["type_"+l]=="string")t[l]=s[c];else if(s["type_"+l]=="number"||s["type_"+l]=="integer"||s["type_"+l]=="float")t[l]=Number(s[c]);else if(s["type_"+l]=="boolean"){const h=(a=s[c])==null?void 0:a.toLocaleLowerCase();t[l]=h=="1"||h=="y"||h=="t"||h=="yes"||h=="true"}}else t[l]=s[c]}return t.factor1="localpassword",s.factor1&&o.includes(s.factor1)&&(t.factor1=s.factor1),t.factor2=s.factor2,t}function lr(p,s,i,o){var t;const e=s.locals.user&&C.isAdminFn(s.locals.user);for(let n in i){let a=n.replace(/^user_/,"");if(n.startsWith("user_")&&(e||o.includes(a)))if("type_"+a in i){if(i["type_"+a]=="string")p[a]=i[n];else if(i["type_"+a]=="number"||i["type_"+a]=="integer"||i["type_"+a]=="float")p[a]=Number(i[n]);else if(i["type_"+a]=="boolean"){const c=(t=i[n])==null?void 0:t.toLocaleLowerCase();p[a]=c=="1"||c=="y"||c=="t"||c=="yes"||c=="true"}}else p[a]=i[n]}return p}class N{constructor(s,i,o={}){this.validateUserFn=nr,this.createUserFn=cr,this.updateUserFn=lr,this.allowedFactor2=[],this.allowedFactor2Names=[],this.factor2ProtectedPageEndpoints=[],this.factor2ProtectedApiEndpoints=[],this.loginProtectedPageEndpoints=[],this.loginProtectedApiEndpoints=[],this.loginProtectedExceptionPageEndpoints=[],this.loginProtectedExceptionApiEndpoints=[],this.adminPageEndpoints=[],this.adminApiEndpoints=[],this.adminProtectedExceptionPageEndpoints=[],this.adminProtectedExceptionApiEndpoints=[],this.unauthorizedUrl=void 0,this.enableCsrfProtection=!0,this.enableEmailVerification=!1,this.enablePasswordReset=!1,this.factor2Url="/factor2",this.loginUrl="/login",this.logoutUrl="/logout",this.userAllowedFactor1=["localpassword"],this.adminAllowedFactor1=["localpassword"],this.keyStorage=s,this.userStorage=o.userStorage,this.clientStorage=o.clientStorage,this.authenticators=i,this.sessionManager=new u.SessionManager(s,i,o),this.redirect=o.redirect??m.redirect,this.error=o.error??m.error,u.setParameter("factor2Url",u.ParamType.String,this,o,"FACTOR2_URL"),this.factor2Url.endsWith("/")||(this.factor2Url+="/"),u.setParameter("factor2ProtectedPageEndpoints",u.ParamType.JsonArray,this,o,"FACTOR2_PROTECTED_PAGE_ENDPOINTS"),u.setParameter("factor2ProtectedApiEndpoints",u.ParamType.JsonArray,this,o,"FACTOR2_PROTECTED_API_ENDPOINTS"),u.setParameter("loginProtectedPageEndpoints",u.ParamType.JsonArray,this,o,"LOGIN_PROTECTED_PAGE_ENDPOINTS"),u.setParameter("loginProtectedApiEndpoints",u.ParamType.JsonArray,this,o,"LOGIN_PROTECTED_API_ENDPOINTS"),u.setParameter("loginProtectedExceptionPageEndpoints",u.ParamType.JsonArray,this,o,"LOGIN_PROTECTED_EXCEPTION_PAGE_ENDPOINTS"),u.setParameter("loginProtectedExceptionApiEndpoints",u.ParamType.JsonArray,this,o,"LOGIN_PROTECTED_EXCEPTION_API_ENDPOINTS"),u.setParameter("adminPageEndpoints",u.ParamType.JsonArray,this,o,"ADMIN_PAGE_ENDPOINTS"),u.setParameter("adminApiEndpoints",u.ParamType.JsonArray,this,o,"ADMIN_API_ENDPOINTS"),u.setParameter("adminProtectedExceptionPageEndpoints",u.ParamType.JsonArray,this,o,"ADMIN_PROTECTED_EXCEPTION_PAGE_ENDPOINTS"),u.setParameter("adminProtectedExceptionApiEndpoints",u.ParamType.JsonArray,this,o,"ADMIN_PROTECTED_EXCEPTION_API_ENDPOINTS"),u.setParameter("loginUrl",u.ParamType.JsonArray,this,o,"LOGIN_URL"),u.setParameter("logoutUrl",u.ParamType.JsonArray,this,o,"LOGOUT_URL"),u.setParameter("unauthorizedUrl",u.ParamType.JsonArray,this,o,"UNAUTHORIZED_PAGE"),u.setParameter("userAllowedFactor1",u.ParamType.JsonArray,this,o,"USER_ALLOWED_FACTOR1"),u.setParameter("adminAllowedFactor1",u.ParamType.JsonArray,this,o,"ADMIN_ALLOWED_FACTOR1");let e={};if(u.setParameter("allowedFactor2",u.ParamType.JsonArray,e,o,"ALLOWED_FACTOR2"),this.allowedFactor2Names=o.allowedFactor2??["none"],e.allowedFactor2)for(let t of e.allowedFactor2)t in this.authenticators?this.allowedFactor2.push({name:t,friendlyName:this.authenticators[t].friendlyName,configurable:this.authenticators[t].secretNames().length>0}):t=="none"&&this.allowedFactor2.push({name:"none",friendlyName:"None",configurable:!1});u.setParameter("enableEmailVerification",u.ParamType.Boolean,this,o,"ENABLE_EMAIL_VERIFICATION"),u.setParameter("enablePasswordReset",u.ParamType.Boolean,this,o,"ENABLE_PASSWORD_RESET"),u.setParameter("enableCsrfProtection",u.ParamType.Boolean,this,o,"ENABLE_CSRF_PROTECTION"),u.setParameter("editUserScope",u.ParamType.String,this,o,"EDIT_USER_SCOPE"),o.validateUserFn&&(this.validateUserFn=o.validateUserFn),o.createUserFn&&(this.createUserFn=o.createUserFn),o.updateUserFn&&(this.updateUserFn=o.updateUserFn),o.addToSession&&(this.addToSession=o.addToSession),o.validateSession&&(this.validateSession=o.validateSession),this.userEndpoints=new V(this,o),this.adminEndpoints=new W(this,o),this.userClientEndpoints=new G(this,o),this.adminClientEndpoints=new Q(this,o),this.sessionHook=async({event:t})=>{var d,f;r.CrossauthLogger.logger.debug(r.j({msg:"Session hook"}));let n=[],a;const c=this.sessionManager.csrfCookieName,l=this.sessionManager.sessionCookieName;if(this.enableCsrfProtection){r.CrossauthLogger.logger.debug(r.j({msg:"Getting csrf cookie"}));let g;try{g=this.getCsrfCookieValue(t),g&&this.sessionManager.validateCsrfCookie(g)}catch(E){r.CrossauthLogger.logger.warn(r.j({msg:"Invalid csrf cookie received",cerr:E,hashedCsrfCookie:this.getHashOfCsrfCookie(t)}));try{this.clearCookie(c,this.sessionManager.csrfCookiePath,t)}catch(w){r.CrossauthLogger.logger.debug(r.j({err:w})),r.CrossauthLogger.logger.error(r.j({cerr:w,msg:"Couldn't delete CSRF cookie",ip:t.request.referrer,hashedCsrfCookie:this.getHashOfCsrfCookie(t)}))}g=void 0,t.locals.csrfToken=void 0}if(["GET","OPTIONS","HEAD"].includes(t.request.method))try{if(g){r.CrossauthLogger.logger.debug(r.j({msg:"Valid CSRF cookie - creating token"}));const E=await this.sessionManager.createCsrfFormOrHeaderValue(g);t.locals.csrfToken=E}else{r.CrossauthLogger.logger.debug(r.j({msg:"Invalid CSRF cookie - recreating"}));const{csrfCookie:E,csrfFormOrHeaderValue:w}=await this.sessionManager.createCsrfToken();this.setCsrfCookie(E,t),t.locals.csrfToken=w}this.setHeader(L,t.locals.csrfToken,n)}catch(E){r.CrossauthLogger.logger.error(r.j({msg:"Couldn't create CSRF token",cerr:E,user:(d=t.locals.user)==null?void 0:d.username,hashedSessionCookie:this.getHashOfSessionCookie(t)})),r.CrossauthLogger.logger.debug(r.j({err:E})),this.clearCookie(c,this.sessionManager.csrfCookiePath,t),t.locals.csrfToken=void 0}else if(g)try{await this.csrfToken(t,n)}catch(E){r.CrossauthLogger.logger.error(r.j({msg:"Couldn't create CSRF token",cerr:E,user:(f=t.locals.user)==null?void 0:f.username,hashedSessionCookie:this.getHashOfSessionCookie(t)})),r.CrossauthLogger.logger.debug(r.j({err:E}))}}t.locals.user=void 0,t.locals.authType=void 0;const h=this.getSessionCookieValue(t);if(r.CrossauthLogger.logger.debug(r.j({msg:"Getting session cookie"})),h)try{const g=this.sessionManager.getSessionId(h);let{key:E,user:w}=await this.sessionManager.userForSessionId(g);this.validateSession&&this.validateSession(E,w,t);const k=t.url.pathname;if(r.CrossauthLogger.logger.debug(r.j({msg:"Session cookie is for user "+w})),w&&this.allowedFactor2.length>0&&(w.state==r.UserState.factor2ResetNeeded||!this.allowedFactor2Names.includes(w.factor2?w.factor2:"none"))){if(!this.userEndpoints.configureFactor2Url)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set configureFactor2Url in session server");if(!this.userEndpoints.changeFactor2Url)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set changeFactor2Url in session server");if(!this.logoutUrl)throw new r.CrossauthError(r.ErrorCode.Configuration,"Must set logoutUrl in session server");[this.userEndpoints.changeFactor2Url,this.userEndpoints.configureFactor2Url,this.loginUrl,this.logoutUrl].includes(k)||(a=302,n.push({name:"location",value:this.userEndpoints.changeFactor2Url+"?required=true&next="+encodeURIComponent("login?next="+t.url)}))}t.locals.sessionId=g,t.locals.user=w,t.locals.authType="cookie",r.CrossauthLogger.logger.debug(r.j({msg:"Valid session id",user:w==null?void 0:w.username}))}catch{r.CrossauthLogger.logger.warn(r.j({msg:"Invalid session cookie received",hashedSessionCookie:this.getHashOfSessionCookie(t)})),this.clearCookie(l,this.sessionManager.sessionCookiePath,t)}return{headers:n,status:a}},this.twoFAHook=async({event:t})=>{var h;if(r.CrossauthLogger.logger.debug(r.j({msg:"twoFAHook",username:(h=t.locals.user)==null?void 0:h.username})),!this.userStorage)throw this.error(500,"No user storage defined");const n=this.getSessionCookieValue(t),a=this.isFactor2PageProtected(t),c=this.isFactor2ApiProtected(t);let l;if(n)if(t.locals.user)l=t.locals.user;else{const d=await this.getSessionData(t,"user");if(d){const f=await this.userStorage.getUserByUsername(d.username,{skipActiveCheck:!0});(f.user.status==r.UserState.active||f.user.state==r.UserState.factor2ResetNeeded)&&(l=f.user)}}if(l&&n&&l.factor2!=""&&(a||c))if(r.CrossauthLogger.logger.debug(r.j({msg:"Factor2-protected endpoint visited"})),["GET","OPTIONS","HEAD"].includes(t.request.method)){r.CrossauthLogger.logger.debug(r.j({msg:"Factor2-protected GET endpoint - cancelling 2FA"}));const d=this.getSessionCookieValue(t);if(d){const f=this.sessionManager.getSessionId(d);if("pre2fa"in await this.sessionManager.dataForSessionId(f)){r.CrossauthLogger.logger.debug(r.j({msg:"Cancelling 2FA"}));try{await this.sessionManager.cancelTwoFactorPageVisit(d)}catch(E){r.CrossauthLogger.logger.debug(r.j({err:E})),r.CrossauthLogger.logger.error(r.j({msg:"Failed cancelling 2FA",cerr:E,user:l.username,hashedSessionCookie:this.getHashOfSessionCookie(t)}))}}}}else{const d=this.sessionManager.getSessionId(n),f=await this.sessionManager.dataForSessionId(d);if("pre2fa"in f){r.CrossauthLogger.logger.debug(r.j({msg:"Completing 2FA"}));const g=this.authenticators[f.pre2fa.factor2],E=[...g.secretNames(),...g.transientSecretNames()];let w={};const k=new S;await k.loadData(t);for(let v of k.keys())E.includes(v)&&(w[v]=k.get(v)??"");const y=this.getSessionCookieValue(t);if(!y)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session cookie found");let _;try{await this.sessionManager.completeTwoFactorPageVisit(w,t.locals.sessionId??"")}catch(v){_=r.CrossauthError.asCrossauthError(v),r.CrossauthLogger.logger.debug(r.j({err:v}));const A=r.CrossauthError.asCrossauthError(v);r.CrossauthLogger.logger.error(r.j({msg:_.message,cerr:v,user:k.get("username"),errorCode:A.code,errorCodeName:A.codeName}))}if(_)if(_.code==r.ErrorCode.Expired){r.CrossauthLogger.logger.debug(r.j({msg:"Error - cancelling 2FA"}));try{await this.sessionManager.cancelTwoFactorPageVisit(y)}catch(v){r.CrossauthLogger.logger.error(r.j({msg:"Failed cancelling 2FA",cerr:v,user:l.username,hashedSessionCookie:this.getHashOfSessionCookie(t)})),r.CrossauthLogger.logger.debug(r.j({err:v}))}return this.error(401,{message:"Sorry, your code has expired"}),{ok:!1,twofa:!0}}else return a?{twofa:!0,ok:!1,response:new Response("",{status:302,statusText:r.httpStatus(302),headers:{Location:this.factor2Url+"?error="+r.ErrorCode[_.code]}})}:{twofa:!0,ok:!1,response:new Response(JSON.stringify({ok:!1,errorMessage:_.message,errorMessages:_.messages,errorCode:_.code,errorCodeName:r.ErrorCode[_.code]}),{status:_.httpStatus,statusText:r.httpStatus(_.httpStatus),headers:{"content-tyoe":"application/json"}})};return N.updateRequest(t,f.pre2fa.body,f.pre2fa["content-type"]),{twofa:!0,ok:!0}}else{if(r.CrossauthLogger.logger.debug(r.j({msg:"Starting 2FA",username:l.username})),this.enableCsrfProtection&&!t.locals.csrfToken){const w=new r.CrossauthError(r.ErrorCode.Forbidden,"CSRF token missing");return{twofa:!0,ok:!1,response:new Response(JSON.stringify({ok:!1,errorMessage:w.message,errorMessages:w.messages,errorCode:w.code,errorCodeName:r.ErrorCode[w.code]}),{status:w.httpStatus,statusText:r.httpStatus(w.httpStatus),headers:{"content-tyoe":"application/json"}})}}const g=new S;await g.loadData(t);let E=t.request.headers.get("content-type");return await this.sessionManager.initiateTwoFactorPageVisit(l,t.locals.sessionId??"",g.toObject(),t.request.url.replace(/\?.*$/,""),E||void 0),a?{twofa:!0,ok:!0,response:new Response("",{status:302,statusText:r.httpStatus(302),headers:{Location:this.factor2Url}})}:{twofa:!0,ok:!0,response:new Response(JSON.stringify({ok:!0,factor2Required:!0}),{headers:{"content-tyoe":"application/json"}})}}}return{twofa:!1,ok:!0}}}getSessionCookieValue(s){if(s.cookies&&s.cookies.get(this.sessionManager.sessionCookieName))return s.cookies.get(this.sessionManager.sessionCookieName)}getCsrfCookieValue(s){if(s.cookies&&s.cookies.get(this.sessionManager.csrfCookieName))return s.cookies.get(this.sessionManager.csrfCookieName)}clearCookie(s,i,o){o.cookies.delete(s,{path:i})}setHeaders(s,i){for(let o of s)i.headers.append(o.name,o.value)}setCsrfCookie(s,i){i.cookies.set(s.name,s.value,u.toCookieSerializeOptions(s.options))}setHeader(s,i,o){o.push({name:s,value:i})}getHashOfSessionCookie(s){const i=this.getSessionCookieValue(s);if(!i)return"";try{return u.Crypto.hash(i)}catch{}return""}getHashOfCsrfCookie(s){const i=this.getCsrfCookieValue(s);if(!i)return"";try{return u.Crypto.hash(i)}catch{}return""}async csrfToken(s,i){var e,t,n;let o;if(s.request.headers&&s.request.headers.has(L.toLowerCase())){const a=s.request.headers.get(L.toLowerCase());Array.isArray(a)?o=a[0]:a&&(o=a)}if(!o){if(!((e=s.request)!=null&&e.body)){r.CrossauthLogger.logger.warn(r.j({msg:"Received CSRF header but not token",ip:s.request.referrerPolicy,hashedCsrfCookie:this.getHashOfCsrfCookie(s)}));return}const a=s.request.headers.get("content-type");if(a=="application/json")o=(await((n=(t=s.request)==null?void 0:t.clone())==null?void 0:n.json())).csrfToken;else if(a=="application/x-www-form-urlencoded"||a=="multipart/form-data"){const l=(await s.request.clone().formData()).get("csrfToken");l&&typeof l=="string"&&(o=l)}}if(o)try{this.sessionManager.validateDoubleSubmitCsrfToken(this.getCsrfCookieValue(s),o),s.locals.csrfToken=o,this.setHeader(L,o,i)}catch{r.CrossauthLogger.logger.warn(r.j({msg:"Invalid CSRF token",hashedCsrfCookie:this.getHashOfCsrfCookie(s)})),this.clearCookie(this.sessionManager.csrfCookieName,this.sessionManager.csrfCookiePath,s),s.locals.csrfToken=void 0}else s.locals.csrfToken=void 0;return o}static updateRequest(s,i,o){let e;if(o=="application/json")e=JSON.stringify(i);else{e="";for(let t in i){const n=i[t];e.length>0&&(e+="&"),e+=encodeURIComponent(t)+"="+encodeURIComponent(n)}}return s.request=new Request(s.request.url,{method:"POST",headers:s.request.headers,body:e}),s}getHashOfSessionId(s){if(!s.locals.sessionId)return"";try{return u.Crypto.hash(s.locals.sessionId)}catch{}return""}async factor2PageVisitStarted(s){try{return this.getSessionData(s,"pre2fa")!=null}catch(i){const o=r.CrossauthError.asCrossauthError(i);return r.CrossauthLogger.logger.debug(r.j({err:o})),r.CrossauthLogger.logger.error(r.j({cerr:o,msg:"Couldn't get pre2fa data from session"})),!1}}isLoginPageProtected(s){const i=new URL(typeof s=="string"?s:s.request.url);if(i.pathname==this.loginUrl)return!1;let o=!1;return o=this.loginProtectedExceptionPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o?!1:this.loginProtectedPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),!1)}isLoginApiProtected(s){const i=new URL(typeof s=="string"?s:s.request.url);if(i.pathname==this.loginUrl)return!1;let o=!1;return o=this.loginProtectedExceptionApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o?!1:this.loginProtectedApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),!1)}isFactor2PageProtected(s){const i=new URL(typeof s=="string"?s:s.request.url);return this.factor2ProtectedPageEndpoints.reduce((e,t)=>e||T.minimatch(i.pathname,t),!1)}isFactor2ApiProtected(s){const i=new URL(typeof s=="string"?s:s.request.url);return this.factor2ProtectedApiEndpoints.reduce((e,t)=>e||T.minimatch(i.pathname,t),!1)}isAdminPageEndpoint(s){const i=new URL(typeof s=="string"?s:s.request.url);let o=!1;return o=this.adminProtectedExceptionPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o||(o=this.loginProtectedExceptionPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o)?!1:this.adminPageEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),!1)}isAdminApiEndpoint(s){const i=new URL(typeof s=="string"?s:s.request.url);let o=!1;return o=this.adminProtectedExceptionApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o||(o=this.loginProtectedExceptionApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),o),o)?!1:this.adminApiEndpoints.reduce((t,n)=>t||T.minimatch(i.pathname,n),!1)}async createAnonymousSession(s,i){r.CrossauthLogger.logger.debug(r.j({msg:"Creating anonympous session ID "}));const o=new S;await o.loadData(s);let e=this.addToSession?this.addToSession(s,o.toObject()):{};i&&(e.data=JSON.stringify(i));let{sessionCookie:t,csrfCookie:n,csrfFormOrHeaderValue:a}=await this.sessionManager.createAnonymousSession(e);s.cookies.set(t.name,t.value,u.toCookieSerializeOptions(t.options)),this.enableCsrfProtection&&(s.locals.csrfToken=a,s.cookies.set(n.name,n.value,u.toCookieSerializeOptions(n.options))),s.locals.user=void 0;const c=this.sessionManager.getSessionId(t.value);return s.locals.sessionId=c,t.value}async refreshLocals(s){try{const i=this.getSessionCookieValue(s);if(i){const o=this.sessionManager.getSessionId(i);s.locals.sessionId=o;const e=await this.sessionManager.userForSessionId(o);s.locals.user=e.user}else s.locals.sessionId=void 0,s.locals.user=void 0}catch(i){r.CrossauthLogger.logger.error(r.j({errr:i}))}}csrfProtectionEnabled(){return this.enableCsrfProtection}getCsrfToken(s){return s.locals.csrfToken}getUser(s){return s.locals.user}async getSessionData(s,i){try{const o=s.locals.sessionId?await this.sessionManager.dataForSessionId(s.locals.sessionId):void 0;if(o&&i in o)return o[i]}catch(o){r.CrossauthLogger.logger.error(r.j({msg:"Couldn't get "+i+"from session",cerr:o})),r.CrossauthLogger.logger.debug(r.j({err:o}))}}async updateSessionData(s,i,o){if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session present");await this.sessionManager.updateSessionData(s.locals.sessionId,i,o)}async updateManySessionData(s,i){if(!s.locals.sessionId)throw new r.CrossauthError(r.ErrorCode.Unauthorized,"No session present");await this.sessionManager.updateManySessionData(s.locals.sessionId,i)}async deleteSessionData(s,i){s.locals.sessionId?await this.sessionManager.deleteSessionData(s.locals.sessionId,i):r.CrossauthLogger.logger.debug(r.j({msg:`Attempting to delete session data ${i} when no session is present`}))}}exports.JsonOrFormData=S;exports.SvelteKitAdminClientEndpoints=Q;exports.SvelteKitAdminEndpoints=W;exports.SvelteKitApiKeyServer=x;exports.SvelteKitAuthorizationServer=B;exports.SvelteKitOAuthClient=j;exports.SvelteKitOAuthResourceServer=H;exports.SvelteKitServer=C;exports.SvelteKitSessionAdapter=tr;exports.SvelteKitSessionServer=N;exports.SvelteKitSharedClientEndpoints=O;exports.SvelteKitUserClientEndpoints=G;exports.SvelteKitUserEndpoints=V;exports.defaultClientSearchFn=J;
|
package/dist/index.js
CHANGED
|
@@ -3206,7 +3206,7 @@ class ye {
|
|
|
3206
3206
|
var s = new U();
|
|
3207
3207
|
await s.loadData(r), o = s.toObject();
|
|
3208
3208
|
const e = s.get("username") ?? "", t = s.getAsBoolean("persist") ?? !1;
|
|
3209
|
-
o.next.includes("/__data.json") && (o.next = o.next.substring(0, o.next.indexOf("/__data.json")));
|
|
3209
|
+
o.next && o.next.includes("/__data.json") && (o.next = o.next.substring(0, o.next.indexOf("/__data.json")));
|
|
3210
3210
|
let a = o.next ?? this.loginRedirectUrl;
|
|
3211
3211
|
if (e == "") throw new c(u.InvalidUsername, "Username field may not be empty");
|
|
3212
3212
|
let i = this.addToSession ? this.addToSession(r, o) : {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UserStorage, KeyStorage, ApiKeyManagerOptions } from '@crossauth/backend';
|
|
2
|
-
import { RequestEvent
|
|
2
|
+
import { RequestEvent } from '@sveltejs/kit';
|
|
3
|
+
import { MaybePromise } from './tests/sveltemocks';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Options for {@link SvelteKitApiKeyServer }.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CrossauthError, ErrorCode, OAuthTokenResponse, OAuthDeviceAuthorizationResponse, User } from '@crossauth/common';
|
|
2
2
|
import { OAuthClientBackend, OAuthClientOptions } from '@crossauth/backend';
|
|
3
3
|
import { SvelteKitServer } from './sveltekitserver';
|
|
4
|
-
import { RequestEvent
|
|
4
|
+
import { RequestEvent } from '@sveltejs/kit';
|
|
5
|
+
import { MaybePromise } from './tests/sveltemocks';
|
|
5
6
|
|
|
6
7
|
export type SvelteKitErrorFn = (server: SvelteKitServer, event: RequestEvent, ce: CrossauthError) => Promise<Response>;
|
|
7
8
|
/**
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { RequestEvent
|
|
1
|
+
import { RequestEvent } from '@sveltejs/kit';
|
|
2
2
|
import { User } from '@crossauth/common';
|
|
3
3
|
import { OAuthResourceServer, UserStorage, OAuthResourceServerOptions, OAuthTokenConsumer } from '@crossauth/backend';
|
|
4
4
|
import { SvelteKitSessionAdapter } from './sveltekitsessionadapter';
|
|
5
|
+
import { MaybePromise } from './tests/sveltemocks';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Options for {@link SvelteKitOAuthResourceServer}
|
|
@@ -3,7 +3,8 @@ import { SvelteKitApiKeyServer, SvelteKitApiKeyServerOptions } from './sveltekit
|
|
|
3
3
|
import { SvelteKitAuthorizationServer, SvelteKitAuthorizationServerOptions } from './sveltekitoauthserver';
|
|
4
4
|
import { UserStorage, KeyStorage, OAuthClientStorage } from '@crossauth/backend';
|
|
5
5
|
import { User } from '@crossauth/common';
|
|
6
|
-
import { Handle, RequestEvent, ResolveOptions
|
|
6
|
+
import { Handle, RequestEvent, ResolveOptions } from '@sveltejs/kit';
|
|
7
|
+
import { MaybePromise } from './tests/sveltemocks';
|
|
7
8
|
import { SvelteKitOAuthClient, SvelteKitOAuthClientOptions } from './sveltekitoauthclient';
|
|
8
9
|
import { SvelteKitOAuthResourceServer, SvelteKitOAuthResourceServerOptions } from './sveltekitresserver';
|
|
9
10
|
import { SvelteKitSessionAdapter } from './sveltekitsessionadapter';
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { KeyStorage, UserStorage, OAuthClientStorage, SessionManager, Authenticator, Cookie, SessionManagerOptions } from '@crossauth/backend';
|
|
2
2
|
import { Key, User, UserInputFields, OAuthClient } from '@crossauth/common';
|
|
3
|
-
import { RequestEvent
|
|
3
|
+
import { RequestEvent } from '@sveltejs/kit';
|
|
4
4
|
import { SvelteKitUserEndpoints } from './sveltekituserendpoints';
|
|
5
5
|
import { SvelteKitAdminEndpoints } from './sveltekitadminendpoints';
|
|
6
6
|
import { SvelteKitUserClientEndpoints } from './sveltekituserclientendpoints';
|
|
7
7
|
import { SvelteKitAdminClientEndpoints } from './sveltekitadminclientendpoints';
|
|
8
8
|
import { SvelteKitSessionAdapter } from './sveltekitsessionadapter';
|
|
9
|
+
import { MaybePromise } from './tests/sveltemocks';
|
|
9
10
|
|
|
10
11
|
export declare const CSRFHEADER = "X-CROSSAUTH-CSRF";
|
|
11
12
|
export type Header = {
|
|
@@ -555,7 +556,7 @@ export declare class SvelteKitSessionServer implements SvelteKitSessionAdapter {
|
|
|
555
556
|
*/
|
|
556
557
|
static updateRequest(event: RequestEvent, params: {
|
|
557
558
|
[key: string]: string;
|
|
558
|
-
}, contentType: string): RequestEvent<
|
|
559
|
+
}, contentType: string): RequestEvent<Record<string, string>, string | null>;
|
|
559
560
|
/**
|
|
560
561
|
* Returns a hash of the session ID. Used for logging (for security,
|
|
561
562
|
* the actual session ID is not logged)
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
import { Cookies,
|
|
1
|
+
import { Cookies, ResolveOptions } from '@sveltejs/kit';
|
|
2
2
|
import { CookieParseOptions, CookieSerializeOptions } from 'cookie';
|
|
3
3
|
|
|
4
|
+
export interface AppTypes {
|
|
5
|
+
RouteId(): string;
|
|
6
|
+
RouteParams(): Record<string, Record<string, string>>;
|
|
7
|
+
LayoutParams(): Record<string, Record<string, string>>;
|
|
8
|
+
Pathname(): string;
|
|
9
|
+
ResolvedPathname(): string;
|
|
10
|
+
Asset(): string;
|
|
11
|
+
}
|
|
12
|
+
declare type RouteId1 = string;
|
|
13
|
+
export type LayoutParams<T extends RouteId1> = T extends keyof ReturnType<AppTypes['LayoutParams']> ? ReturnType<AppTypes['LayoutParams']>[T] : Record<string, never>;
|
|
14
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
4
15
|
export declare class MockCookies implements Cookies {
|
|
5
16
|
cookies: {
|
|
6
17
|
[key: string]: {
|
|
@@ -29,9 +40,7 @@ export declare class MockCookies implements Cookies {
|
|
|
29
40
|
path: string;
|
|
30
41
|
}): string;
|
|
31
42
|
}
|
|
32
|
-
export declare class MockRequestEvent<Params extends
|
|
33
|
-
[key: string]: string;
|
|
34
|
-
}, RouteId extends string | null = string> implements RequestEvent<Params, RouteId> {
|
|
43
|
+
export declare class MockRequestEvent<Params extends LayoutParams<'/'> = LayoutParams<'/'>, RouteId extends RouteId1 | null = RouteId1 | null> {
|
|
35
44
|
constructor(id: RouteId, request: Request, params: Params, { isDataRequest, isSubRequest, cookies, baseUrl }?: {
|
|
36
45
|
isDataRequest?: boolean;
|
|
37
46
|
isSubRequest?: boolean;
|
|
@@ -53,20 +62,26 @@ export declare class MockRequestEvent<Params extends Partial<Record<string, stri
|
|
|
53
62
|
route: {
|
|
54
63
|
id: RouteId;
|
|
55
64
|
};
|
|
56
|
-
headers
|
|
65
|
+
headers?: {
|
|
57
66
|
[key: string]: string;
|
|
58
67
|
} | undefined;
|
|
59
68
|
setHeaders(headers: Record<string, string>): void;
|
|
60
69
|
url: URL;
|
|
61
70
|
isDataRequest: boolean;
|
|
62
71
|
isSubRequest: boolean;
|
|
72
|
+
tracing: {
|
|
73
|
+
enabled: boolean;
|
|
74
|
+
root: any;
|
|
75
|
+
current: any;
|
|
76
|
+
};
|
|
77
|
+
isRemoteRequest: boolean;
|
|
63
78
|
}
|
|
64
79
|
export interface MockResolveOptions extends ResolveOptions {
|
|
65
80
|
body?: string;
|
|
66
81
|
status?: number;
|
|
67
82
|
statusText?: string;
|
|
68
83
|
}
|
|
69
|
-
type MockResolve = (event: MockRequestEvent, _opts?: ResolveOptions) => MaybePromise<Response>;
|
|
84
|
+
type MockResolve = (event: MockRequestEvent<Record<string, string>, string | null>, _opts?: ResolveOptions | undefined) => MaybePromise<Response>;
|
|
70
85
|
export declare class MockResolver {
|
|
71
86
|
body: string | undefined;
|
|
72
87
|
status: number;
|
package/package.json
CHANGED
|
@@ -1,28 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crossauth/sveltekit",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
+
"description": "Sveltekit adapter for Crossauth authentication package",
|
|
5
6
|
"private": false,
|
|
6
7
|
"type": "module",
|
|
7
|
-
"
|
|
8
|
-
"module": "./dist/index.js",
|
|
9
|
-
"typings": "./dist/index.d.ts",
|
|
8
|
+
"svelte": "./dist/index.js",
|
|
10
9
|
"types": "./dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/*",
|
|
12
|
+
"!dist/**/*.test.*",
|
|
13
|
+
"!dist/**/*.spec.*"
|
|
14
|
+
],
|
|
11
15
|
"exports": {
|
|
12
16
|
".": {
|
|
13
17
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"
|
|
15
|
-
"import": "./dist/index.js",
|
|
16
|
-
"default": "./dist/index.js"
|
|
18
|
+
"svelte": "./dist/index.js"
|
|
17
19
|
}
|
|
18
20
|
},
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"svelte": ">=4.0.0"
|
|
23
|
+
},
|
|
24
|
+
"sideEffects": [
|
|
25
|
+
"**/*.css"
|
|
21
26
|
],
|
|
22
27
|
"devDependencies": {
|
|
23
28
|
"@sveltejs/adapter-auto": "^3.0.0",
|
|
24
29
|
"@sveltejs/kit": "^2.5.22",
|
|
25
30
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
|
31
|
+
"@types/node": "^25.0.3",
|
|
26
32
|
"@types/web": "^0.0.154",
|
|
27
33
|
"autoprefixer": "^10.4.18",
|
|
28
34
|
"daisyui": "^4.7.2",
|
|
@@ -34,7 +40,8 @@
|
|
|
34
40
|
"tsx": "^4.7.0",
|
|
35
41
|
"typescript": "^5.0.0 <=5.3.3",
|
|
36
42
|
"vite": "^5.0.3",
|
|
37
|
-
"
|
|
43
|
+
"vite-plugin-dts": "^3.6.4",
|
|
44
|
+
"vitest": "^1.6.1",
|
|
38
45
|
"vitest-fetch-mock": "^0.2.2"
|
|
39
46
|
},
|
|
40
47
|
"dependencies": {
|
|
@@ -45,9 +52,8 @@
|
|
|
45
52
|
"jwt-decode": "^4.0.0",
|
|
46
53
|
"minimatch": "^10.0.1",
|
|
47
54
|
"qrcode": "^1.5.4",
|
|
48
|
-
"
|
|
49
|
-
"@crossauth/
|
|
50
|
-
"@crossauth/common": "^1.0.1"
|
|
55
|
+
"@crossauth/backend": "^1.1.0",
|
|
56
|
+
"@crossauth/common": "^1.1.0"
|
|
51
57
|
},
|
|
52
58
|
"scripts": {
|
|
53
59
|
"preparex": "svelte-kit sync",
|
|
@@ -56,7 +62,7 @@
|
|
|
56
62
|
"preview": "vite preview",
|
|
57
63
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
58
64
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
59
|
-
"test": "dotenv -e .env.unittest vitest",
|
|
65
|
+
"test": "dotenv -e .env.unittest vitest --exclude src/demo.spec.ts",
|
|
60
66
|
"testonce": "dotenv -e .env.unittest vitest run"
|
|
61
67
|
}
|
|
62
68
|
}
|