UNPKG

@bitblit/ratchet-warden-server

Version:

Typescript library to simplify using simplewebauthn and secondary auth methods over GraphQL

104 lines 5.44 kB
import { Logger } from '@bitblit/ratchet-common/logger/logger'; import { ErrorRatchet } from '@bitblit/ratchet-common/lang/error-ratchet'; import { StringRatchet } from '@bitblit/ratchet-common/lang/string-ratchet'; import { Base64Ratchet } from '@bitblit/ratchet-common/lang/base64-ratchet'; import { WardenContactType } from '@bitblit/ratchet-warden-common/common/model/warden-contact-type'; import { WardenCustomerMessageType } from '@bitblit/ratchet-warden-common/common/model/warden-customer-message-type'; export class WardenMailerAndExpiringCodeRatchetSingleUseCodeProvider { mailer; expiringCodeRatchet; mailerOptions; static defaultOptions() { const rval = { emailBaseLayoutName: undefined, expiringTokenHtmlTemplateName: 'expiring-token-request-email', expiringTokenTxtTemplateName: undefined, magicLinkHtmlTemplateName: 'magic-token-request-email', magicLinkTxtTemplateName: undefined, }; return rval; } constructor(mailer, expiringCodeRatchet, mailerOptions = WardenMailerAndExpiringCodeRatchetSingleUseCodeProvider.defaultOptions()) { this.mailer = mailer; this.expiringCodeRatchet = expiringCodeRatchet; this.mailerOptions = mailerOptions; } handlesContactType(type) { return type === WardenContactType.EmailAddress; } async createAndSendNewCode(contact, relyingPartyName, origin) { let rval = null; const token = await this.expiringCodeRatchet.createNewCode({ context: contact.value, length: 6, alphabet: '0123456789', timeToLiveSeconds: 300, tags: ['Login'], }); const msg = await this.formatMessage(contact, WardenCustomerMessageType.ExpiringCode, { requestor: contact.value, requestorB64: Base64Ratchet.encodeStringToBase64String(contact.value), code: token.code, relyingPartyName: relyingPartyName, origin: origin }); rval = await this.sendMessage(msg); return rval; } async checkCode(contactValue, code) { const rval = await this.expiringCodeRatchet.checkCode(code, contactValue); return rval; } async createCodeAndSendMagicLink(loginContact, relyingPartyName, landingUrl, metaIn, ttlSeconds, destinationContact, customTemplate) { let rval = null; const token = await this.expiringCodeRatchet.createNewCode({ context: loginContact.value, length: 36, alphabet: StringRatchet.UPPER_CASE_LATIN, timeToLiveSeconds: ttlSeconds, tags: ['MagicLink'], }); const meta = Object.assign({}, metaIn || {}, { contact: loginContact }); const encodedMeta = Base64Ratchet.safeObjectToBase64JSON(meta || {}); const landingUrlFilled = StringRatchet.simpleTemplateFill(landingUrl, { CODE: token.code, META: encodedMeta }, true, '{', '}'); const context = Object.assign({}, meta || {}, { landingUrl: landingUrlFilled, code: token.code, relyingPartyName: relyingPartyName, }); const msgType = customTemplate ? WardenCustomerMessageType.Custom : WardenCustomerMessageType.MagicLink; const msg = await this.formatMessage(loginContact, msgType, context, destinationContact, customTemplate); rval = await this.sendMessage(msg); return rval; } async formatMessage(contact, messageType, context, destinationContact, customTemplate) { const rts = { destinationAddresses: [destinationContact?.value || contact.value], subject: customTemplate?.subjectLine || this.mailerOptions.magicLinkSubjectLine || 'Login token for ' + contact.value, }; Logger.info('Formatting Message for magic link, rts: %j, messageType: %s, context: %j', rts, messageType, context); if (messageType === WardenCustomerMessageType.ExpiringCode) { await this.mailer.fillEmailBody(rts, context, this.mailerOptions.expiringTokenHtmlTemplateName, this.mailerOptions.expiringTokenTxtTemplateName, this.mailerOptions.emailBaseLayoutName); } else if (messageType === WardenCustomerMessageType.MagicLink) { await this.mailer.fillEmailBody(rts, context, this.mailerOptions.magicLinkHtmlTemplateName, this.mailerOptions.magicLinkTxtTemplateName, this.mailerOptions.emailBaseLayoutName); } else if (messageType === WardenCustomerMessageType.Custom) { if (!customTemplate) { throw ErrorRatchet.fErr('Cannot send custom message if customTemplate not set'); } Logger.info('Sending custom template : %j', customTemplate); await this.mailer.fillEmailBody(rts, context, customTemplate.htmlVersion, customTemplate.textVersion, customTemplate.baseLayout === 'DEFAULT' ? this.mailerOptions.emailBaseLayoutName : customTemplate.baseLayout); } else { throw ErrorRatchet.fErr('No such message type : %s', messageType); } return rts; } async sendMessage(message) { const rval = await this.mailer.sendEmail(message); Logger.debug('SendRawEmailResponse was : %j', rval); return !!rval; } } //# sourceMappingURL=warden-mailer-and-expiring-code-ratchet-single-use-code-provider.js.map