ee5ae8af62
* explicitly ordering global middlewares * various subscription fixes & WIP project invite middleware * SSR invite accept & toast notifs seem to work * backend support for mixpanel * mixpanel be logic -> shared * minor fix * finissh * lint fix * minor comment adjustments * better adblock handling
198 lines
5.5 KiB
JavaScript
198 lines
5.5 KiB
JavaScript
'use strict'
|
|
|
|
const ExpressSession = require('express-session')
|
|
const RedisStore = require('connect-redis')(ExpressSession)
|
|
const passport = require('passport')
|
|
|
|
const sentry = require('@/logging/sentryHelper')
|
|
const { createAuthorizationCode } = require('./services/apps')
|
|
const {
|
|
getFrontendOrigin,
|
|
getMailchimpStatus,
|
|
getMailchimpNewsletterIds,
|
|
getMailchimpOnboardingIds
|
|
} = require('@/modules/shared/helpers/envHelper')
|
|
const { isSSLServer, getRedisUrl } = require('@/modules/shared/helpers/envHelper')
|
|
const { authLogger, logger } = require('@/logging/logging')
|
|
const { createRedisClient } = require('@/modules/shared/redis/redis')
|
|
const { mixpanel } = require('@/modules/shared/utils/mixpanel')
|
|
const {
|
|
addToMailchimpAudience,
|
|
triggerMailchimpCustomerJourney
|
|
} = require('./services/mailchimp')
|
|
const { getUserById } = require('@/modules/core/services/users')
|
|
/**
|
|
* TODO: Get rid of session entirely, we don't use it for the app and it's not really necessary for the auth flow, so it only complicates things
|
|
* NOTE: it does seem used!
|
|
*/
|
|
|
|
module.exports = async (app) => {
|
|
const authStrategies = []
|
|
|
|
passport.serializeUser((user, done) => done(null, user))
|
|
passport.deserializeUser((user, done) => done(null, user))
|
|
app.use(passport.initialize())
|
|
|
|
const redisClient = createRedisClient(getRedisUrl())
|
|
const session = ExpressSession({
|
|
store: new RedisStore({ client: redisClient }),
|
|
secret: process.env.SESSION_SECRET,
|
|
saveUninitialized: false,
|
|
resave: false,
|
|
cookie: {
|
|
maxAge: 1000 * 60 * 3, // 3 minutes
|
|
secure: isSSLServer()
|
|
}
|
|
})
|
|
|
|
/**
|
|
* Move incoming auth query params to session, for easier access (?)
|
|
*/
|
|
const sessionStorage = (req, res, next) => {
|
|
if (!req.query.challenge)
|
|
return res.status(400).send('Invalid request: no challenge detected.')
|
|
|
|
req.session.challenge = req.query.challenge
|
|
|
|
const token = req.query.token || req.query.inviteId
|
|
if (token) {
|
|
req.session.token = token
|
|
}
|
|
|
|
const newsletterConsent = req.query.newsletter || null
|
|
if (newsletterConsent) {
|
|
req.session.newsletterConsent = true
|
|
}
|
|
|
|
next()
|
|
}
|
|
|
|
/**
|
|
Finalizes authentication for the main frontend application.
|
|
@param {import('express').Request} req
|
|
*/
|
|
const finalizeAuth = async (req, res) => {
|
|
try {
|
|
const ac = await createAuthorizationCode({
|
|
appId: 'spklwebapp',
|
|
userId: req.user.id,
|
|
challenge: req.session.challenge
|
|
})
|
|
|
|
let newsletterConsent = false
|
|
if (req.session.newsletterConsent) newsletterConsent = true // NOTE: it's only set if it's true
|
|
|
|
if (req.session) req.session.destroy()
|
|
|
|
// Resolve redirect URL
|
|
const urlObj = new URL(req.authRedirectPath || '/', getFrontendOrigin())
|
|
urlObj.searchParams.set('access_code', ac)
|
|
|
|
if (req.user.isNewUser) {
|
|
urlObj.searchParams.set('register', 'true')
|
|
|
|
// Send event to MP
|
|
const userEmail = req.user.email
|
|
const isInvite = !!req.user.isInvite
|
|
if (userEmail) {
|
|
await mixpanel({ userEmail, req }).track('Sign Up', {
|
|
isInvite
|
|
})
|
|
}
|
|
|
|
if (getMailchimpStatus()) {
|
|
try {
|
|
const user = await getUserById({ userId: req.user.id })
|
|
if (!user)
|
|
throw new Error(
|
|
'Could not register user for mailchimp lists - no db user record found.'
|
|
)
|
|
const onboardingIds = getMailchimpOnboardingIds()
|
|
await triggerMailchimpCustomerJourney(user, onboardingIds)
|
|
|
|
if (newsletterConsent) {
|
|
const { listId } = getMailchimpNewsletterIds()
|
|
await addToMailchimpAudience(user, listId)
|
|
}
|
|
} catch (error) {
|
|
logger.warn(error, 'Failed to sign up user to mailchimp lists')
|
|
}
|
|
}
|
|
}
|
|
|
|
const redirectUrl = urlObj.toString()
|
|
|
|
return res.redirect(redirectUrl)
|
|
} catch (err) {
|
|
sentry({ err })
|
|
authLogger.error(err, 'Could not finalize auth')
|
|
if (req.session) req.session.destroy()
|
|
return res.status(401).send({ err: err.message })
|
|
}
|
|
}
|
|
|
|
/*
|
|
Strategies initialisation & listing
|
|
*/
|
|
|
|
let strategyCount = 0
|
|
|
|
if (process.env.STRATEGY_GOOGLE === 'true') {
|
|
const googStrategy = await require('./strategies/google')(
|
|
app,
|
|
session,
|
|
sessionStorage,
|
|
finalizeAuth
|
|
)
|
|
authStrategies.push(googStrategy)
|
|
strategyCount++
|
|
}
|
|
|
|
if (process.env.STRATEGY_GITHUB === 'true') {
|
|
const githubStrategy = await require('./strategies/github')(
|
|
app,
|
|
session,
|
|
sessionStorage,
|
|
finalizeAuth
|
|
)
|
|
authStrategies.push(githubStrategy)
|
|
strategyCount++
|
|
}
|
|
|
|
if (process.env.STRATEGY_AZURE_AD === 'true') {
|
|
const azureAdStrategy = await require('./strategies/azure-ad')(
|
|
app,
|
|
session,
|
|
sessionStorage,
|
|
finalizeAuth
|
|
)
|
|
authStrategies.push(azureAdStrategy)
|
|
strategyCount++
|
|
}
|
|
|
|
if (process.env.STRATEGY_OIDC === 'true') {
|
|
const oidcStrategy = await require('./strategies/oidc')(
|
|
app,
|
|
session,
|
|
sessionStorage,
|
|
finalizeAuth
|
|
)
|
|
authStrategies.push(oidcStrategy)
|
|
strategyCount++
|
|
}
|
|
|
|
// Note: always leave the local strategy init for last so as to be able to
|
|
// force enable it in case no others are present.
|
|
if (process.env.STRATEGY_LOCAL === 'true' || strategyCount === 0) {
|
|
const localStrategy = await require('./strategies/local')(
|
|
app,
|
|
session,
|
|
sessionStorage,
|
|
finalizeAuth
|
|
)
|
|
authStrategies.push(localStrategy)
|
|
}
|
|
|
|
return authStrategies
|
|
}
|