@bitblit/ratchet-warden-server 4.0.417-alpha → 4.0.420-alpha

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.
Files changed (2) hide show
  1. package/lib/index.mjs +1 -1
  2. package/package.json +7 -7
package/lib/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{generateRegistrationOptions as e,verifyRegistrationResponse as t,generateAuthenticationOptions as n,verifyAuthenticationResponse as r}from"@simplewebauthn/server";import{WardenUtils as i,WardenStoreRegistrationResponseType as a,WardenContactType as o,WardenCustomerMessageType as s}from"@bitblit/ratchet-warden-common";import{RequireRatchet as c,Logger as d,ErrorRatchet as l,StringRatchet as u,Base64Ratchet as h,Mailer as g,TwilioVerifyRatchet as p}from"@bitblit/ratchet-common";import{injectable as m}from"tsyringe";import{ExpiringCodeRatchet as f,S3CacheRatchet as y}from"@bitblit/ratchet-aws";import{S3Client as w}from"@aws-sdk/client-s3";class v{constructor(){}static buildInformation(){return{version:"417",hash:"54671e038cfc7beabb6cbe21856eb79b5f7b2fd8",branch:"alpha-2024-07-30-1",tag:"alpha-2024-07-30-1",timeBuiltISO:"2024-07-30T16:07:46-0700",notes:"No notes"}}}function C(e,t,n,r){var i,a=arguments.length,o=a<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(a<3?i(o):a>3?i(t,n,o):i(t,n))||o);return a>3&&o&&Object.defineProperty(t,n,o),o}function T(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}"function"==typeof SuppressedError&&SuppressedError;let I=class{async fetchDecoration(e){return{userTokenData:i.stripWardenEntryToSummary(e),userTokenExpirationSeconds:3600,userTeamRoles:[{team:"WARDEN",role:"USER"}]}}};I=C([m()],I);let E=class{async userCreated(e){}async userRemoved(e){}};E=C([m()],E);let L=class{async allowMagicLinkCommand(e,t,n){if(!e)throw new Error("Cannot process null magic link");if(e.ttlSeconds&&e.ttlSeconds>3600)throw new Error("TTL may not exceed 3600 seconds");if(e.overrideDestinationContact)throw new Error("You may not specify an overrideDestinationContact")}};L=C([m()],L);let A=class{inOptions;opts;constructor(e){this.inOptions=e,c.notNullOrUndefined(e,"options"),c.notNullOrUndefined(e.relyingPartyName,"options.relyingPartyName"),c.notNullUndefinedOrEmptyArray(e.allowedOrigins,"options.allowedOrigins"),c.notNullOrUndefined(e.storageProvider,"options.storageProvider"),c.notNullOrUndefined(e.jwtRatchet,"options.jwtRatchet"),c.notNullUndefinedOrEmptyArray(e.singleUseCodeProviders,"options.singleUseCodeProviders"),this.opts=Object.assign({userTokenDataProvider:new I,eventProcessor:new E,sendMagicLinkCommandValidator:new L},e)}get options(){return Object.assign({},this.opts)}findEntryByContact(e){return this.opts.storageProvider.findEntryByContact(e)}findEntryById(e){return this.opts.storageProvider.findEntryById(e)}async processCommandStringToString(e,t,n){let r=null;try{const i=JSON.parse(e),a=await this.processCommandToResponse(i,t,n);null===a?d.warn("Response was null for %s %s %s",e,t,n):r=JSON.stringify(a)}catch(t){const n=l.safeStringifyErr(t);d.error("Failed %s : %j",n,e,t),r=JSON.stringify({error:n})}return r}async processCommandToResponse(e,t,n){let r=null;if(e){if(d.info("Processing command : UserID: %s Origin: %s Command: %j",n,t,e),e.sendExpiringValidationToken)r={sendExpiringValidationToken:await this.sendExpiringValidationToken(e.sendExpiringValidationToken)};else if(e.generateWebAuthnAuthenticationChallengeForUserId){const n=await this.generateWebAuthnAuthenticationChallengeForUserId(e.generateWebAuthnAuthenticationChallengeForUserId,t);r={generateWebAuthnAuthenticationChallengeForUserId:{dataAsJson:JSON.stringify(n)}}}else if(e.createAccount)r={createAccount:await this.createAccount(e.createAccount.contact,e.createAccount.sendCode,e.createAccount.label,e.createAccount.tags)};else if(e.sendMagicLink){if(e?.sendMagicLink?.contactLookup&&e?.sendMagicLink?.contact)throw l.fErr("You may not specify both contact and contactLookup");if(!e?.sendMagicLink?.contactLookup&&!e?.sendMagicLink?.contact)throw l.fErr("You must not specify either contact and contactLookup");if(e.sendMagicLink.contactLookup){const t=await this.findEntryById(e.sendMagicLink.contactLookup.userId);t&&(e.sendMagicLink.contactLookup.contactType?e.sendMagicLink.contact=(t.contactMethods||[]).find((t=>t.type===e.sendMagicLink.contactLookup.contactType)):e.sendMagicLink.contact=(t.contactMethods||[]).length>0?t.contactMethods[0]:null),e.sendMagicLink.contactLookup=null}if(!e.sendMagicLink.contact)throw l.fErr("Could not find contract entry either directly or by lookup");const i=u.trimToNull(n)?await this.opts.storageProvider.findEntryById(n):null;await this.opts.sendMagicLinkCommandValidator.allowMagicLinkCommand(e.sendMagicLink,t,i);const a=e?.sendMagicLink?.ttlSeconds||300;r={sendMagicLink:await this.sendMagicLink(e.sendMagicLink.contact,e.sendMagicLink.overrideDestinationContact,this.opts.relyingPartyName,e.sendMagicLink.landingUrl,e.sendMagicLink.meta,a,e.sendMagicLink.customTemplate)}}else if(e.generateWebAuthnRegistrationChallengeForLoggedInUser){u.trimToNull(n)||l.throwFormattedErr("This requires a logged in user");const e=await this.generateWebAuthnRegistrationChallengeForLoggedInUser(n,t);r={generateWebAuthnRegistrationChallengeForLoggedInUser:{dataAsJson:JSON.stringify(e)}}}else if(e.addContactToLoggedInUser)if(i.validContact(e.addContactToLoggedInUser)){r={addContactToLoggedInUser:await this.addContactMethodToUser(n,e.addContactToLoggedInUser)}}else l.throwFormattedErr("Cannot add, invalid contact %j",e.addContactToLoggedInUser);else if(e.addWebAuthnRegistrationToLoggedInUser){u.trimToNull(n)||l.throwFormattedErr("This requires a logged in user");const a=JSON.parse(e.addWebAuthnRegistrationToLoggedInUser.webAuthn.dataAsJson),o=await this.storeAuthnRegistration(n,t,e.addWebAuthnRegistrationToLoggedInUser.applicationName,e.addWebAuthnRegistrationToLoggedInUser.deviceLabel,a);r=o.updatedEntry?{addWebAuthnRegistrationToLoggedInUser:i.stripWardenEntryToSummary(o.updatedEntry)}:o.error?{error:o.error}:{error:"Cannot happen - neither user nor error set"}}else if(e.removeWebAuthnRegistration){const t=await this.removeSingleWebAuthnRegistration(e.removeWebAuthnRegistration.userId,e.removeWebAuthnRegistration.credentialId);r={removeWebAuthnRegistration:i.stripWardenEntryToSummary(t)}}else if(e.removeWebAuthnRegistrationFromLoggedInUser){const t=await this.removeSingleWebAuthnRegistration(n,e.removeWebAuthnRegistrationFromLoggedInUser);r={removeWebAuthnRegistrationFromLoggedInUser:i.stripWardenEntryToSummary(t)}}else if(e.removeContactFromLoggedInUser){const t=await this.removeContactMethodFromUser(n,e.removeContactFromLoggedInUser);r={removeContactFromLoggedInUser:i.stripWardenEntryToSummary(t)}}else if(e.performLogin){const n=e.performLogin,a=await this.processLogin(n,t);if(d.info("Performing login - login auth check was : %s",a),a){const e=u.trimToNull(n.userId)?await this.opts.storageProvider.findEntryById(n.userId):await this.opts.storageProvider.findEntryByContact(n.contact),t=await this.opts.userDecorationProvider.fetchDecoration(e),a={loginData:i.stripWardenEntryToSummary(e),user:t.userTokenData,roles:i.teamRolesToRoles(t.userTeamRoles),proxy:null},o=await this.opts.jwtRatchet.createTokenString(a,t.userTokenExpirationSeconds);r={performLogin:{request:n,userId:e.userId,jwtToken:o}}}else r={error:"Login failed"}}else if(e.refreshJwtToken){const t=await this.opts.jwtRatchet.decodeToken(e.refreshJwtToken,1),n=await this.opts.storageProvider.findEntryById(t.loginData.userId),a=await this.opts.userDecorationProvider.fetchDecoration(n),o={loginData:i.stripWardenEntryToSummary(n),user:a.userTokenData,roles:i.teamRolesToRoles(a.userTeamRoles),proxy:null};r={refreshJwtToken:await this.opts.jwtRatchet.createTokenString(o,a.userTokenExpirationSeconds)}}}else r={error:"No command sent"};return r}urlIsOnAllowedOrigin(e){let t=!1;if(e){const n=new URL(e);for(let e=0;e<this.opts.allowedOrigins.length&&!t;e++){const r=new URL(this.opts.allowedOrigins[e]);t=r.origin===n.origin&&r.protocol===n.protocol&&r.port===n.port}}return t}singleUseCodeProvider(e,t,n){const r=this.opts.singleUseCodeProviders.find((n=>n.handlesContactType(e.type)&&(!t||n.createCodeAndSendMagicLink)));if(!r&&!n)throw l.fErr("Cannot find a single use code provider for contact type : %s",e.type);return r}async sendMagicLink(e,t,n,r,i,a,o){let s=!1;if(c.notNullOrUndefined(e,"contact"),c.notNullUndefinedOrOnlyWhitespaceString(r,"landingUrl"),c.true(this.urlIsOnAllowedOrigin(r),"landingUrl is not on an allowed origin for redirect"),e?.type&&u.trimToNull(e?.value)){const c=this.singleUseCodeProvider(e,!0);s=await c.createCodeAndSendMagicLink(e,n,r,i,a,t,o)}else l.throwFormattedErr("Cannot send - invalid contact %j",e);return s}async createAccount(e,t,n,r){let a=null;if(i.validContact(e)){await this.opts.storageProvider.findEntryByContact(e)&&l.throwFormattedErr("Cannot create - account already exists for %j",e);const i=u.createType4Guid(),o=Date.now(),s={userId:i,userLabel:n||"User "+i,contactMethods:[e],tags:r||[],webAuthnAuthenticators:[],createdEpochMS:o,updatedEpochMS:o},c=await this.opts.storageProvider.saveEntry(s);a=c.userId,this?.opts?.eventProcessor&&await this.opts.eventProcessor.userCreated(c),t&&(d.info("New user %j created and send requested - sending",c),await this.sendExpiringValidationToken(e))}else l.throwFormattedErr("Cannot create - invalid contact (missing or invalid fields)");return a}async addContactMethodToUser(e,t){let n=!1;if(u.trimToNull(e)&&i.validContact(t)){const r=await this.opts.storageProvider.findEntryByContact(t);r&&r.userId!==e&&l.throwFormattedErr("Cannot add contact to this user, another user already has that contact");const i=await this.opts.storageProvider.findEntryById(e);i||l.throwFormattedErr("Cannot add contact to this user, user does not exist"),i.contactMethods.push(t),await this.opts.storageProvider.saveEntry(i),n=!0}else l.throwFormattedErr("Cannot add - invalid config : %s %j",e,t);return n}async removeContactMethodFromUser(e,t){let n=null;if(u.trimToNull(e)&&i.validContact(t)){const r=await this.opts.storageProvider.findEntryById(e);r||l.throwFormattedErr("Cannot remove contact from this user, user does not exist"),r.contactMethods=(r.contactMethods||[]).filter((e=>e.type!==t.type||e.value!==t.value)),0===r.contactMethods.length&&l.throwFormattedErr("Cannot remove the last contact method from a user"),await this.opts.storageProvider.saveEntry(r),n=await this.opts.storageProvider.findEntryById(e)}else l.throwFormattedErr("Cannot add - invalid config : %s %j",e,t);return n}async generateWebAuthnRegistrationChallengeForLoggedInUser(t,n){if(!n||!this.opts.allowedOrigins.includes(n))throw new Error("Invalid origin : "+n);const r=new URL(n).hostname,i=await this.opts.storageProvider.findEntryById(t);if(!i)throw l.fErr("Cannot generateWebAuthnRegistrationChallengeForLoggedInUser - no user %s / %s",t,n);const a=await e({rpName:this.opts.relyingPartyName,rpID:r,userID:u.stringToUint8Array(i.userId),userName:i.userLabel,attestationType:"none",excludeCredentials:i.webAuthnAuthenticators.map((e=>({id:e.credentialPublicKeyBase64,transports:e.transports})))});return await this.opts.storageProvider.updateUserChallenge(i.userId,r,a.challenge),a}async storeAuthnRegistration(e,n,r,i,o){d.info("Store authn data : %j",o);let s=null;try{if(!n||!this.opts.allowedOrigins.includes(n))throw new Error("Invalid origin : "+n);const c=new URL(n).hostname,u=await this.opts.storageProvider.findEntryById(e);if(!u)throw l.fErr("Cannot storeAuthnRegistration - no user %s / %s",e,n);const g={response:o,expectedChallenge:await this.opts.storageProvider.fetchCurrentUserChallenge(u.userId,c),expectedOrigin:n,expectedRPID:c};d.info("Calling verifyRegistrationResponse: %j",g);const p=await t(g);if(d.info("verifyRegistrationResponse Result : %j",p),s={updatedEntry:null,registrationResponseId:o.id,result:p.verified?a.Verified:a.Failed},s.result===a.Verified){d.info("Storing registration");const e={origin:n,applicationName:r||"Unknown Application",deviceLabel:i||"Unknown Device",counter:p.registrationInfo.counter,credentialBackedUp:p.registrationInfo.credentialBackedUp,credentialDeviceType:p.registrationInfo.credentialDeviceType,credentialIdBase64:p.registrationInfo.credentialID,credentialPublicKeyBase64:h.uint8ArrayToBase64UrlString(p.registrationInfo.credentialPublicKey)};u.webAuthnAuthenticators=(u.webAuthnAuthenticators||[]).filter((t=>t.credentialIdBase64!==e.credentialIdBase64)),u.webAuthnAuthenticators.push(e);const t=await this.opts.storageProvider.saveEntry(u);s.updatedEntry=t,d.info("Stored auth : %j",t)}}catch(e){s={registrationResponseId:o.id,result:a.Error,error:l.safeStringifyErr(e)}}return s}async generateWebAuthnAuthenticationChallengeForUserId(e,t){const n=await this.opts.storageProvider.findEntryById(e);return await this.generateWebAuthnAuthenticationChallenge(n,t)}async generateWebAuthnAuthenticationChallenge(e,t){const r=e.webAuthnAuthenticators;if(!t||!this.opts.allowedOrigins.includes(t))throw new Error("Invalid origin : "+t);const i=new URL(t).hostname,a={rpID:i,allowCredentials:r.map((e=>({id:e.credentialIdBase64,transports:e.transports}))),userVerification:"preferred"},o=await n(a);return await this.opts.storageProvider.updateUserChallenge(e.userId,i,o.challenge),o}async sendExpiringValidationToken(e){let t=!1;if(e?.type&&u.trimToNull(e?.value)){const n=this.singleUseCodeProvider(e,!1);t=await n.createAndSendNewCode(e,this.opts.relyingPartyName)}else l.throwFormattedErr("Cannot send - invalid request %j",e);return t}async processLogin(e,t){d.info("Processing login : %s : %j",t,e);let n=!1;c.notNullOrUndefined(e,"request"),c.true(!!u.trimToNull(e?.userId)||i.validContact(e?.contact),"Invalid contact and no userId"),c.true(!!e?.webAuthn||!!u.trimToNull(e?.expiringToken),"You must provide one of webAuthn or expiringToken"),c.true(!e?.webAuthn||!u.trimToNull(e?.expiringToken),"WebAuthn and ExpiringToken may not BOTH be set");let r=u.trimToNull(e?.userId)?await this.opts.storageProvider.findEntryById(e?.userId):await this.opts.storageProvider.findEntryByContact(e.contact);if(!r){if(d.info("User not found, and createUserIfMissing=%s / %j",e.createUserIfMissing,e.contact),e.createUserIfMissing&&e.contact){const t=await this.createAccount(e.contact);d.info("Finished create, new id is %s",t),r=await this.opts.storageProvider.findEntryById(t)}r||l.throwFormattedErr("No user found for %j / %s",e?.contact,e?.userId)}if(e.webAuthn)n=await this.loginWithWebAuthnRequest(r,t,e.webAuthn);else if(u.trimToNull(e.expiringToken)){const t=this.singleUseCodeProvider(e.contact,!1);await t.checkCode(e.contact.value,e.expiringToken)?n=!0:l.throwFormattedErr("Cannot login - token is invalid for this user")}return n}async loginWithWebAuthnRequest(e,t,n){let i=!1;const a=new URL(t).hostname,o=await this.opts.storageProvider.fetchCurrentUserChallenge(e.userId,a),s=(e.webAuthnAuthenticators||[]).find((e=>e.credentialIdBase64===n.id));if(!s){const t=(e.webAuthnAuthenticators||[]).map((e=>e.credentialIdBase64));throw l.fErr("Could not find authenticator %s (%s) for user %s (avail were : %j)",n.id,n.id,e.userId,t)}const c={counter:s.counter,credentialID:s.credentialIdBase64,credentialPublicKey:h.base64UrlStringToBytes(s.credentialPublicKeyBase64)},d={response:n,expectedChallenge:o,expectedOrigin:t,expectedRPID:a,authenticator:c};return(await r(d)).verified&&(i=!0),i}async removeSingleWebAuthnRegistration(e,t){let n=await this.opts.storageProvider.findEntryById(e);return n?(n.webAuthnAuthenticators=(n.webAuthnAuthenticators||[]).filter((e=>e.credentialIdBase64!==t)),n=await this.opts.storageProvider.saveEntry(n)):d.info("Not removing - no such user as %s",e),n}async removeUser(e){let t=!1;if(u.trimToNull(e)){const n=await this.opts.storageProvider.findEntryById(e);n?(await this.opts.storageProvider.removeEntry(e),this?.opts?.eventProcessor&&await this.opts.eventProcessor.userRemoved(n),t=!0):d.warn("Cannot remove non-existent user : %s",e)}return t}};var k;A=C([m(),T("design:paramtypes",[Object])],A);let b=k=class{mailer;expiringCodeRatchet;mailerOptions;static defaultOptions(){return{emailBaseLayoutName:void 0,expiringTokenHtmlTemplateName:"expiring-token-request-email",expiringTokenTxtTemplateName:void 0,magicLinkHtmlTemplateName:"magic-token-request-email",magicLinkTxtTemplateName:void 0}}constructor(e,t,n=k.defaultOptions()){this.mailer=e,this.expiringCodeRatchet=t,this.mailerOptions=n}handlesContactType(e){return e===o.EmailAddress}async createAndSendNewCode(e,t){let n=null;const r=await this.expiringCodeRatchet.createNewCode({context:e.value,length:6,alphabet:"0123456789",timeToLiveSeconds:300,tags:["Login"]}),i=await this.formatMessage(e,s.ExpiringCode,{code:r.code,relyingPartyName:t});return n=await this.sendMessage(i),n}async checkCode(e,t){return await this.expiringCodeRatchet.checkCode(t,e)}async createCodeAndSendMagicLink(e,t,n,r,i,a,o){let c=null;const d=await this.expiringCodeRatchet.createNewCode({context:e.value,length:36,alphabet:u.UPPER_CASE_LATIN,timeToLiveSeconds:i,tags:["MagicLink"]}),l=Object.assign({},r||{},{contact:e}),g=h.safeObjectToBase64JSON(l||{});let p=u.simpleTemplateFill(n,{CODE:d.code,META:g},!0,"{","}");const m=Object.assign({},l||{},{landingUrl:p,code:d.code,relyingPartyName:t}),f=o?s.Custom:s.MagicLink,y=await this.formatMessage(e,f,m,a,o);return c=await this.sendMessage(y),c}async formatMessage(e,t,n,r,i){const a={destinationAddresses:[r?.value||e.value],subject:i?.subjectLine||this.mailerOptions.magicLinkSubjectLine||"Your login token"};if(d.info("Formatting Message for magic link, rts: %j, messageType: %s, context: %j",a,t,n),t===s.ExpiringCode)await this.mailer.fillEmailBody(a,n,this.mailerOptions.expiringTokenHtmlTemplateName,this.mailerOptions.expiringTokenTxtTemplateName,this.mailerOptions.emailBaseLayoutName);else if(t===s.MagicLink)await this.mailer.fillEmailBody(a,n,this.mailerOptions.magicLinkHtmlTemplateName,this.mailerOptions.magicLinkTxtTemplateName,this.mailerOptions.emailBaseLayoutName);else{if(t!==s.Custom)throw l.fErr("No such message type : %s",t);if(!i)throw l.fErr("Cannot send custom message if customTemplate not set");d.info("Sending custom template : %j",i),await this.mailer.fillEmailBody(a,n,i.htmlVersion,i.textVersion,"DEFAULT"===i.baseLayout?this.mailerOptions.emailBaseLayoutName:i.baseLayout)}return a}async sendMessage(e){const t=await this.mailer.sendEmail(e);return d.debug("SendRawEmailResponse was : %j",t),!!t}};b=k=C([m(),T("design:paramtypes",[g,f,Object])],b);let U=class{s3;options;ratchet;constructor(e,t){this.s3=e,this.options=t,this.ratchet=new y(this.s3,this.options.bucket)}async listUserSummaries(){return(await this.fetchDataFile()).entries.map((e=>i.stripWardenEntryToSummary(e)))}async fetchDataFile(){let e=await this.ratchet.fetchCacheFileAsObject(this.options.dataFileKey);return e=e||{entries:[],challenges:[]},e}async storeDataFile(e){let t=null;return e&&(t=await this.ratchet.writeObjectToCacheFile(this.options.dataFileKey,e)),t}async fetchCurrentUserChallenge(e,t){const n=((await this.fetchDataFile()).challenges||[]).find((n=>n.userId===e&&n.relyingPartyId===t));return n||l.throwFormattedErr("fetchCurrentUserChallenge: Could not find user %s",e),n.challenge}async findEntryByContact(e){let t=null;if(e?.type&&u.trimToNull(e?.value)){t=((await this.fetchDataFile()).entries||[]).find((t=>!!(t.contactMethods||[]).find((t=>t.type===e.type&&t.value===e.value))))}return t}async findEntryById(e){let t=null;if(u.trimToNull(e)){t=((await this.fetchDataFile()).entries||[]).find((t=>t.userId===e))}return t}async removeEntry(e){const t=await this.fetchDataFile();return t.entries=(t.entries||[]).filter((t=>t.userId!==e)),await this.storeDataFile(t),!0}async saveEntry(e){let t=null;if(e&&e.userId){const n=Date.now();e.createdEpochMS=e.createdEpochMS||n,e.updatedEpochMS=n;const r=await this.fetchDataFile();r.entries=(r.entries||[]).filter((t=>t.userId!==e.userId)),r.entries.push(e),await this.storeDataFile(r),t=await this.findEntryById(e.userId)}return t}async updateUserChallenge(e,t,n){const r=await this.fetchDataFile();return r.challenges=(r.challenges||[]).filter((n=>n.userId!==e||n.relyingPartyId!==t)),r.challenges.push({userId:e,relyingPartyId:t,challenge:n,updatedEpochMS:Date.now()}),await this.storeDataFile(r),!0}};U=C([m(),T("design:paramtypes",[w,Object])],U);let R=class{optsPromise;_cacheTwilioVerifyRatchet;constructor(e){this.optsPromise=e}async twilioVerifyRatchet(){if(!this._cacheTwilioVerifyRatchet){const e=await this.optsPromise;this._cacheTwilioVerifyRatchet=new p(e.accountSID,e.authToken,e.verifyServiceSID)}return this._cacheTwilioVerifyRatchet}handlesContactType(e){return e===o.TextCapablePhoneNumber}async createAndSendNewCode(e,t){const n=await this.twilioVerifyRatchet(),r=await n.sendVerificationTokenUsingTwilioVerify(e.value);return d.debug("sendMessage was : %j",r),!!r}async checkCode(e,t){const n=await this.twilioVerifyRatchet();return await n.simpleCheckVerificationTokenUsingTwilioVerify(e,t)}};R=C([m(),T("design:paramtypes",[Promise])],R);export{v as RatchetWardenServerInfo,L as WardenDefaultSendMagicLinkCommandValidator,I as WardenDefaultUserDecorationProvider,b as WardenMailerAndExpiringCodeRatchetSingleUseCodeProvider,E as WardenNoOpEventProcessingProvider,U as WardenS3SingleFileStorageProvider,A as WardenService,R as WardenTwilioVerifySingleUseCodeProvider};
1
+ import{generateRegistrationOptions as e,verifyRegistrationResponse as t,generateAuthenticationOptions as n,verifyAuthenticationResponse as r}from"@simplewebauthn/server";import{WardenUtils as i,WardenStoreRegistrationResponseType as a,WardenContactType as o,WardenCustomerMessageType as s}from"@bitblit/ratchet-warden-common";import{RequireRatchet as c,Logger as d,ErrorRatchet as l,StringRatchet as h,Base64Ratchet as u,TwilioVerifyRatchet as g}from"@bitblit/ratchet-common";import{S3CacheRatchet as p}from"@bitblit/ratchet-aws";class m{constructor(){}static buildInformation(){return{version:"420",hash:"4470745cd9544530657f21b58e096ebea701451a",branch:"alpha-2024-07-30-6",tag:"alpha-2024-07-30-6",timeBuiltISO:"2024-07-30T23:41:38-0700",notes:"No notes"}}}class f{async fetchDecoration(e){return{userTokenData:i.stripWardenEntryToSummary(e),userTokenExpirationSeconds:3600,userTeamRoles:[{team:"WARDEN",role:"USER"}]}}}class y{async userCreated(e){}async userRemoved(e){}}class w{async allowMagicLinkCommand(e,t,n){if(!e)throw new Error("Cannot process null magic link");if(e.ttlSeconds&&e.ttlSeconds>3600)throw new Error("TTL may not exceed 3600 seconds");if(e.overrideDestinationContact)throw new Error("You may not specify an overrideDestinationContact")}}class C{inOptions;opts;constructor(e){this.inOptions=e,c.notNullOrUndefined(e,"options"),c.notNullOrUndefined(e.relyingPartyName,"options.relyingPartyName"),c.notNullUndefinedOrEmptyArray(e.allowedOrigins,"options.allowedOrigins"),c.notNullOrUndefined(e.storageProvider,"options.storageProvider"),c.notNullOrUndefined(e.jwtRatchet,"options.jwtRatchet"),c.notNullUndefinedOrEmptyArray(e.singleUseCodeProviders,"options.singleUseCodeProviders"),this.opts=Object.assign({userTokenDataProvider:new f,eventProcessor:new y,sendMagicLinkCommandValidator:new w},e)}get options(){return Object.assign({},this.opts)}findEntryByContact(e){return this.opts.storageProvider.findEntryByContact(e)}findEntryById(e){return this.opts.storageProvider.findEntryById(e)}async processCommandStringToString(e,t,n){let r=null;try{const i=JSON.parse(e),a=await this.processCommandToResponse(i,t,n);null===a?d.warn("Response was null for %s %s %s",e,t,n):r=JSON.stringify(a)}catch(t){const n=l.safeStringifyErr(t);d.error("Failed %s : %j",n,e,t),r=JSON.stringify({error:n})}return r}async processCommandToResponse(e,t,n){let r=null;if(e){if(d.info("Processing command : UserID: %s Origin: %s Command: %j",n,t,e),e.sendExpiringValidationToken)r={sendExpiringValidationToken:await this.sendExpiringValidationToken(e.sendExpiringValidationToken)};else if(e.generateWebAuthnAuthenticationChallengeForUserId){const n=await this.generateWebAuthnAuthenticationChallengeForUserId(e.generateWebAuthnAuthenticationChallengeForUserId,t);r={generateWebAuthnAuthenticationChallengeForUserId:{dataAsJson:JSON.stringify(n)}}}else if(e.createAccount)r={createAccount:await this.createAccount(e.createAccount.contact,e.createAccount.sendCode,e.createAccount.label,e.createAccount.tags)};else if(e.sendMagicLink){if(e?.sendMagicLink?.contactLookup&&e?.sendMagicLink?.contact)throw l.fErr("You may not specify both contact and contactLookup");if(!e?.sendMagicLink?.contactLookup&&!e?.sendMagicLink?.contact)throw l.fErr("You must not specify either contact and contactLookup");if(e.sendMagicLink.contactLookup){const t=await this.findEntryById(e.sendMagicLink.contactLookup.userId);t&&(e.sendMagicLink.contactLookup.contactType?e.sendMagicLink.contact=(t.contactMethods||[]).find((t=>t.type===e.sendMagicLink.contactLookup.contactType)):e.sendMagicLink.contact=(t.contactMethods||[]).length>0?t.contactMethods[0]:null),e.sendMagicLink.contactLookup=null}if(!e.sendMagicLink.contact)throw l.fErr("Could not find contract entry either directly or by lookup");const i=h.trimToNull(n)?await this.opts.storageProvider.findEntryById(n):null;await this.opts.sendMagicLinkCommandValidator.allowMagicLinkCommand(e.sendMagicLink,t,i);const a=e?.sendMagicLink?.ttlSeconds||300;r={sendMagicLink:await this.sendMagicLink(e.sendMagicLink.contact,e.sendMagicLink.overrideDestinationContact,this.opts.relyingPartyName,e.sendMagicLink.landingUrl,e.sendMagicLink.meta,a,e.sendMagicLink.customTemplate)}}else if(e.generateWebAuthnRegistrationChallengeForLoggedInUser){h.trimToNull(n)||l.throwFormattedErr("This requires a logged in user");const e=await this.generateWebAuthnRegistrationChallengeForLoggedInUser(n,t);r={generateWebAuthnRegistrationChallengeForLoggedInUser:{dataAsJson:JSON.stringify(e)}}}else if(e.addContactToLoggedInUser)if(i.validContact(e.addContactToLoggedInUser)){r={addContactToLoggedInUser:await this.addContactMethodToUser(n,e.addContactToLoggedInUser)}}else l.throwFormattedErr("Cannot add, invalid contact %j",e.addContactToLoggedInUser);else if(e.addWebAuthnRegistrationToLoggedInUser){h.trimToNull(n)||l.throwFormattedErr("This requires a logged in user");const a=JSON.parse(e.addWebAuthnRegistrationToLoggedInUser.webAuthn.dataAsJson),o=await this.storeAuthnRegistration(n,t,e.addWebAuthnRegistrationToLoggedInUser.applicationName,e.addWebAuthnRegistrationToLoggedInUser.deviceLabel,a);r=o.updatedEntry?{addWebAuthnRegistrationToLoggedInUser:i.stripWardenEntryToSummary(o.updatedEntry)}:o.error?{error:o.error}:{error:"Cannot happen - neither user nor error set"}}else if(e.removeWebAuthnRegistration){const t=await this.removeSingleWebAuthnRegistration(e.removeWebAuthnRegistration.userId,e.removeWebAuthnRegistration.credentialId);r={removeWebAuthnRegistration:i.stripWardenEntryToSummary(t)}}else if(e.removeWebAuthnRegistrationFromLoggedInUser){const t=await this.removeSingleWebAuthnRegistration(n,e.removeWebAuthnRegistrationFromLoggedInUser);r={removeWebAuthnRegistrationFromLoggedInUser:i.stripWardenEntryToSummary(t)}}else if(e.removeContactFromLoggedInUser){const t=await this.removeContactMethodFromUser(n,e.removeContactFromLoggedInUser);r={removeContactFromLoggedInUser:i.stripWardenEntryToSummary(t)}}else if(e.performLogin){const n=e.performLogin,a=await this.processLogin(n,t);if(d.info("Performing login - login auth check was : %s",a),a){const e=h.trimToNull(n.userId)?await this.opts.storageProvider.findEntryById(n.userId):await this.opts.storageProvider.findEntryByContact(n.contact),t=await this.opts.userDecorationProvider.fetchDecoration(e),a={loginData:i.stripWardenEntryToSummary(e),user:t.userTokenData,roles:i.teamRolesToRoles(t.userTeamRoles),proxy:null},o=await this.opts.jwtRatchet.createTokenString(a,t.userTokenExpirationSeconds);r={performLogin:{request:n,userId:e.userId,jwtToken:o}}}else r={error:"Login failed"}}else if(e.refreshJwtToken){const t=await this.opts.jwtRatchet.decodeToken(e.refreshJwtToken,1),n=await this.opts.storageProvider.findEntryById(t.loginData.userId),a=await this.opts.userDecorationProvider.fetchDecoration(n),o={loginData:i.stripWardenEntryToSummary(n),user:a.userTokenData,roles:i.teamRolesToRoles(a.userTeamRoles),proxy:null};r={refreshJwtToken:await this.opts.jwtRatchet.createTokenString(o,a.userTokenExpirationSeconds)}}}else r={error:"No command sent"};return r}urlIsOnAllowedOrigin(e){let t=!1;if(e){const n=new URL(e);for(let e=0;e<this.opts.allowedOrigins.length&&!t;e++){const r=new URL(this.opts.allowedOrigins[e]);t=r.origin===n.origin&&r.protocol===n.protocol&&r.port===n.port}}return t}singleUseCodeProvider(e,t,n){const r=this.opts.singleUseCodeProviders.find((n=>n.handlesContactType(e.type)&&(!t||n.createCodeAndSendMagicLink)));if(!r&&!n)throw l.fErr("Cannot find a single use code provider for contact type : %s",e.type);return r}async sendMagicLink(e,t,n,r,i,a,o){let s=!1;if(c.notNullOrUndefined(e,"contact"),c.notNullUndefinedOrOnlyWhitespaceString(r,"landingUrl"),c.true(this.urlIsOnAllowedOrigin(r),"landingUrl is not on an allowed origin for redirect"),e?.type&&h.trimToNull(e?.value)){const c=this.singleUseCodeProvider(e,!0);s=await c.createCodeAndSendMagicLink(e,n,r,i,a,t,o)}else l.throwFormattedErr("Cannot send - invalid contact %j",e);return s}async createAccount(e,t,n,r){let a=null;if(i.validContact(e)){await this.opts.storageProvider.findEntryByContact(e)&&l.throwFormattedErr("Cannot create - account already exists for %j",e);const i=h.createType4Guid(),o=Date.now(),s={userId:i,userLabel:n||"User "+i,contactMethods:[e],tags:r||[],webAuthnAuthenticators:[],createdEpochMS:o,updatedEpochMS:o},c=await this.opts.storageProvider.saveEntry(s);a=c.userId,this?.opts?.eventProcessor&&await this.opts.eventProcessor.userCreated(c),t&&(d.info("New user %j created and send requested - sending",c),await this.sendExpiringValidationToken(e))}else l.throwFormattedErr("Cannot create - invalid contact (missing or invalid fields)");return a}async addContactMethodToUser(e,t){let n=!1;if(h.trimToNull(e)&&i.validContact(t)){const r=await this.opts.storageProvider.findEntryByContact(t);r&&r.userId!==e&&l.throwFormattedErr("Cannot add contact to this user, another user already has that contact");const i=await this.opts.storageProvider.findEntryById(e);i||l.throwFormattedErr("Cannot add contact to this user, user does not exist"),i.contactMethods.push(t),await this.opts.storageProvider.saveEntry(i),n=!0}else l.throwFormattedErr("Cannot add - invalid config : %s %j",e,t);return n}async removeContactMethodFromUser(e,t){let n=null;if(h.trimToNull(e)&&i.validContact(t)){const r=await this.opts.storageProvider.findEntryById(e);r||l.throwFormattedErr("Cannot remove contact from this user, user does not exist"),r.contactMethods=(r.contactMethods||[]).filter((e=>e.type!==t.type||e.value!==t.value)),0===r.contactMethods.length&&l.throwFormattedErr("Cannot remove the last contact method from a user"),await this.opts.storageProvider.saveEntry(r),n=await this.opts.storageProvider.findEntryById(e)}else l.throwFormattedErr("Cannot add - invalid config : %s %j",e,t);return n}async generateWebAuthnRegistrationChallengeForLoggedInUser(t,n){if(!n||!this.opts.allowedOrigins.includes(n))throw new Error("Invalid origin : "+n);const r=new URL(n).hostname,i=await this.opts.storageProvider.findEntryById(t);if(!i)throw l.fErr("Cannot generateWebAuthnRegistrationChallengeForLoggedInUser - no user %s / %s",t,n);const a=await e({rpName:this.opts.relyingPartyName,rpID:r,userID:h.stringToUint8Array(i.userId),userName:i.userLabel,attestationType:"none",excludeCredentials:i.webAuthnAuthenticators.map((e=>({id:e.credentialPublicKeyBase64,transports:e.transports})))});return await this.opts.storageProvider.updateUserChallenge(i.userId,r,a.challenge),a}async storeAuthnRegistration(e,n,r,i,o){d.info("Store authn data : %j",o);let s=null;try{if(!n||!this.opts.allowedOrigins.includes(n))throw new Error("Invalid origin : "+n);const c=new URL(n).hostname,h=await this.opts.storageProvider.findEntryById(e);if(!h)throw l.fErr("Cannot storeAuthnRegistration - no user %s / %s",e,n);const g={response:o,expectedChallenge:await this.opts.storageProvider.fetchCurrentUserChallenge(h.userId,c),expectedOrigin:n,expectedRPID:c};d.info("Calling verifyRegistrationResponse: %j",g);const p=await t(g);if(d.info("verifyRegistrationResponse Result : %j",p),s={updatedEntry:null,registrationResponseId:o.id,result:p.verified?a.Verified:a.Failed},s.result===a.Verified){d.info("Storing registration");const e={origin:n,applicationName:r||"Unknown Application",deviceLabel:i||"Unknown Device",counter:p.registrationInfo.counter,credentialBackedUp:p.registrationInfo.credentialBackedUp,credentialDeviceType:p.registrationInfo.credentialDeviceType,credentialIdBase64:p.registrationInfo.credentialID,credentialPublicKeyBase64:u.uint8ArrayToBase64UrlString(p.registrationInfo.credentialPublicKey)};h.webAuthnAuthenticators=(h.webAuthnAuthenticators||[]).filter((t=>t.credentialIdBase64!==e.credentialIdBase64)),h.webAuthnAuthenticators.push(e);const t=await this.opts.storageProvider.saveEntry(h);s.updatedEntry=t,d.info("Stored auth : %j",t)}}catch(e){s={registrationResponseId:o.id,result:a.Error,error:l.safeStringifyErr(e)}}return s}async generateWebAuthnAuthenticationChallengeForUserId(e,t){const n=await this.opts.storageProvider.findEntryById(e);return await this.generateWebAuthnAuthenticationChallenge(n,t)}async generateWebAuthnAuthenticationChallenge(e,t){const r=e.webAuthnAuthenticators;if(!t||!this.opts.allowedOrigins.includes(t))throw new Error("Invalid origin : "+t);const i=new URL(t).hostname,a={rpID:i,allowCredentials:r.map((e=>({id:e.credentialIdBase64,transports:e.transports}))),userVerification:"preferred"},o=await n(a);return await this.opts.storageProvider.updateUserChallenge(e.userId,i,o.challenge),o}async sendExpiringValidationToken(e){let t=!1;if(e?.type&&h.trimToNull(e?.value)){const n=this.singleUseCodeProvider(e,!1);t=await n.createAndSendNewCode(e,this.opts.relyingPartyName)}else l.throwFormattedErr("Cannot send - invalid request %j",e);return t}async processLogin(e,t){d.info("Processing login : %s : %j",t,e);let n=!1;c.notNullOrUndefined(e,"request"),c.true(!!h.trimToNull(e?.userId)||i.validContact(e?.contact),"Invalid contact and no userId"),c.true(!!e?.webAuthn||!!h.trimToNull(e?.expiringToken),"You must provide one of webAuthn or expiringToken"),c.true(!e?.webAuthn||!h.trimToNull(e?.expiringToken),"WebAuthn and ExpiringToken may not BOTH be set");let r=h.trimToNull(e?.userId)?await this.opts.storageProvider.findEntryById(e?.userId):await this.opts.storageProvider.findEntryByContact(e.contact);if(!r){if(d.info("User not found, and createUserIfMissing=%s / %j",e.createUserIfMissing,e.contact),e.createUserIfMissing&&e.contact){const t=await this.createAccount(e.contact);d.info("Finished create, new id is %s",t),r=await this.opts.storageProvider.findEntryById(t)}r||l.throwFormattedErr("No user found for %j / %s",e?.contact,e?.userId)}if(e.webAuthn)n=await this.loginWithWebAuthnRequest(r,t,e.webAuthn);else if(h.trimToNull(e.expiringToken)){const t=this.singleUseCodeProvider(e.contact,!1);await t.checkCode(e.contact.value,e.expiringToken)?n=!0:l.throwFormattedErr("Cannot login - token is invalid for this user")}return n}async loginWithWebAuthnRequest(e,t,n){let i=!1;const a=new URL(t).hostname,o=await this.opts.storageProvider.fetchCurrentUserChallenge(e.userId,a),s=(e.webAuthnAuthenticators||[]).find((e=>e.credentialIdBase64===n.id));if(!s){const t=(e.webAuthnAuthenticators||[]).map((e=>e.credentialIdBase64));throw l.fErr("Could not find authenticator %s (%s) for user %s (avail were : %j)",n.id,n.id,e.userId,t)}const c={counter:s.counter,credentialID:s.credentialIdBase64,credentialPublicKey:u.base64UrlStringToBytes(s.credentialPublicKeyBase64)},d={response:n,expectedChallenge:o,expectedOrigin:t,expectedRPID:a,authenticator:c};return(await r(d)).verified&&(i=!0),i}async removeSingleWebAuthnRegistration(e,t){let n=await this.opts.storageProvider.findEntryById(e);return n?(n.webAuthnAuthenticators=(n.webAuthnAuthenticators||[]).filter((e=>e.credentialIdBase64!==t)),n=await this.opts.storageProvider.saveEntry(n)):d.info("Not removing - no such user as %s",e),n}async removeUser(e){let t=!1;if(h.trimToNull(e)){const n=await this.opts.storageProvider.findEntryById(e);n?(await this.opts.storageProvider.removeEntry(e),this?.opts?.eventProcessor&&await this.opts.eventProcessor.userRemoved(n),t=!0):d.warn("Cannot remove non-existent user : %s",e)}return t}}class v{mailer;expiringCodeRatchet;mailerOptions;static defaultOptions(){return{emailBaseLayoutName:void 0,expiringTokenHtmlTemplateName:"expiring-token-request-email",expiringTokenTxtTemplateName:void 0,magicLinkHtmlTemplateName:"magic-token-request-email",magicLinkTxtTemplateName:void 0}}constructor(e,t,n=v.defaultOptions()){this.mailer=e,this.expiringCodeRatchet=t,this.mailerOptions=n}handlesContactType(e){return e===o.EmailAddress}async createAndSendNewCode(e,t){let n=null;const r=await this.expiringCodeRatchet.createNewCode({context:e.value,length:6,alphabet:"0123456789",timeToLiveSeconds:300,tags:["Login"]}),i=await this.formatMessage(e,s.ExpiringCode,{code:r.code,relyingPartyName:t});return n=await this.sendMessage(i),n}async checkCode(e,t){return await this.expiringCodeRatchet.checkCode(t,e)}async createCodeAndSendMagicLink(e,t,n,r,i,a,o){let c=null;const d=await this.expiringCodeRatchet.createNewCode({context:e.value,length:36,alphabet:h.UPPER_CASE_LATIN,timeToLiveSeconds:i,tags:["MagicLink"]}),l=Object.assign({},r||{},{contact:e}),g=u.safeObjectToBase64JSON(l||{});let p=h.simpleTemplateFill(n,{CODE:d.code,META:g},!0,"{","}");const m=Object.assign({},l||{},{landingUrl:p,code:d.code,relyingPartyName:t}),f=o?s.Custom:s.MagicLink,y=await this.formatMessage(e,f,m,a,o);return c=await this.sendMessage(y),c}async formatMessage(e,t,n,r,i){const a={destinationAddresses:[r?.value||e.value],subject:i?.subjectLine||this.mailerOptions.magicLinkSubjectLine||"Your login token"};if(d.info("Formatting Message for magic link, rts: %j, messageType: %s, context: %j",a,t,n),t===s.ExpiringCode)await this.mailer.fillEmailBody(a,n,this.mailerOptions.expiringTokenHtmlTemplateName,this.mailerOptions.expiringTokenTxtTemplateName,this.mailerOptions.emailBaseLayoutName);else if(t===s.MagicLink)await this.mailer.fillEmailBody(a,n,this.mailerOptions.magicLinkHtmlTemplateName,this.mailerOptions.magicLinkTxtTemplateName,this.mailerOptions.emailBaseLayoutName);else{if(t!==s.Custom)throw l.fErr("No such message type : %s",t);if(!i)throw l.fErr("Cannot send custom message if customTemplate not set");d.info("Sending custom template : %j",i),await this.mailer.fillEmailBody(a,n,i.htmlVersion,i.textVersion,"DEFAULT"===i.baseLayout?this.mailerOptions.emailBaseLayoutName:i.baseLayout)}return a}async sendMessage(e){const t=await this.mailer.sendEmail(e);return d.debug("SendRawEmailResponse was : %j",t),!!t}}class T{s3;options;ratchet;constructor(e,t){this.s3=e,this.options=t,this.ratchet=new p(this.s3,this.options.bucket)}async listUserSummaries(){return(await this.fetchDataFile()).entries.map((e=>i.stripWardenEntryToSummary(e)))}async fetchDataFile(){let e=await this.ratchet.fetchCacheFileAsObject(this.options.dataFileKey);return e=e||{entries:[],challenges:[]},e}async storeDataFile(e){let t=null;return e&&(t=await this.ratchet.writeObjectToCacheFile(this.options.dataFileKey,e)),t}async fetchCurrentUserChallenge(e,t){const n=((await this.fetchDataFile()).challenges||[]).find((n=>n.userId===e&&n.relyingPartyId===t));return n||l.throwFormattedErr("fetchCurrentUserChallenge: Could not find user %s",e),n.challenge}async findEntryByContact(e){let t=null;if(e?.type&&h.trimToNull(e?.value)){t=((await this.fetchDataFile()).entries||[]).find((t=>!!(t.contactMethods||[]).find((t=>t.type===e.type&&t.value===e.value))))}return t}async findEntryById(e){let t=null;if(h.trimToNull(e)){t=((await this.fetchDataFile()).entries||[]).find((t=>t.userId===e))}return t}async removeEntry(e){const t=await this.fetchDataFile();return t.entries=(t.entries||[]).filter((t=>t.userId!==e)),await this.storeDataFile(t),!0}async saveEntry(e){let t=null;if(e&&e.userId){const n=Date.now();e.createdEpochMS=e.createdEpochMS||n,e.updatedEpochMS=n;const r=await this.fetchDataFile();r.entries=(r.entries||[]).filter((t=>t.userId!==e.userId)),r.entries.push(e),await this.storeDataFile(r),t=await this.findEntryById(e.userId)}return t}async updateUserChallenge(e,t,n){const r=await this.fetchDataFile();return r.challenges=(r.challenges||[]).filter((n=>n.userId!==e||n.relyingPartyId!==t)),r.challenges.push({userId:e,relyingPartyId:t,challenge:n,updatedEpochMS:Date.now()}),await this.storeDataFile(r),!0}}class I{optsPromise;_cacheTwilioVerifyRatchet;constructor(e){this.optsPromise=e}async twilioVerifyRatchet(){if(!this._cacheTwilioVerifyRatchet){const e=await this.optsPromise;this._cacheTwilioVerifyRatchet=new g(e.accountSID,e.authToken,e.verifyServiceSID)}return this._cacheTwilioVerifyRatchet}handlesContactType(e){return e===o.TextCapablePhoneNumber}async createAndSendNewCode(e,t){const n=await this.twilioVerifyRatchet(),r=await n.sendVerificationTokenUsingTwilioVerify(e.value);return d.debug("sendMessage was : %j",r),!!r}async checkCode(e,t){const n=await this.twilioVerifyRatchet();return await n.simpleCheckVerificationTokenUsingTwilioVerify(e,t)}}export{m as RatchetWardenServerInfo,w as WardenDefaultSendMagicLinkCommandValidator,f as WardenDefaultUserDecorationProvider,v as WardenMailerAndExpiringCodeRatchetSingleUseCodeProvider,y as WardenNoOpEventProcessingProvider,T as WardenS3SingleFileStorageProvider,C as WardenService,I as WardenTwilioVerifySingleUseCodeProvider};
2
2
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitblit/ratchet-warden-server",
3
- "version": "4.0.417-alpha",
3
+ "version": "4.0.420-alpha",
4
4
  "description": "Typescript library to simplify using simplewebauthn and secondary auth methods over GraphQL",
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -49,9 +49,9 @@
49
49
  "dependencies": {
50
50
  "@aws-sdk/client-s3": "3.600.0",
51
51
  "@aws-sdk/client-ses": "3.600.0",
52
- "@bitblit/ratchet-aws": "4.0.417-alpha",
53
- "@bitblit/ratchet-common": "4.0.417-alpha",
54
- "@bitblit/ratchet-warden-common": "4.0.417-alpha",
52
+ "@bitblit/ratchet-aws": "4.0.420-alpha",
53
+ "@bitblit/ratchet-common": "4.0.420-alpha",
54
+ "@bitblit/ratchet-warden-common": "4.0.420-alpha",
55
55
  "@simplewebauthn/browser": "10.0.0",
56
56
  "@simplewebauthn/server": "10.0.0",
57
57
  "jsonwebtoken": "9.0.2"
@@ -59,9 +59,9 @@
59
59
  "peerDependencies": {
60
60
  "@aws-sdk/client-s3": "^3.600.0",
61
61
  "@aws-sdk/client-ses": "^3.600.0",
62
- "@bitblit/ratchet-aws": "4.0.417-alpha",
63
- "@bitblit/ratchet-common": "4.0.417-alpha",
64
- "@bitblit/ratchet-warden-common": "4.0.417-alpha",
62
+ "@bitblit/ratchet-aws": "4.0.420-alpha",
63
+ "@bitblit/ratchet-common": "4.0.420-alpha",
64
+ "@bitblit/ratchet-warden-common": "4.0.420-alpha",
65
65
  "@simplewebauthn/browser": "^10.0.0",
66
66
  "@simplewebauthn/server": "^10.0.0",
67
67
  "@simplewebauthn/types": "^10.0.0",