mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
cd8693db40
Add generic POST gateway to handle samesite=lax session cookies GitOrigin-RevId: e50a0fde63659a77a047e545a22fba5339f16427
96 lines
2.7 KiB
JavaScript
96 lines
2.7 KiB
JavaScript
const Settings = require('settings-sharelatex')
|
|
const Errors = require('../Features/Errors/Errors')
|
|
|
|
// SessionAutostartMiddleware provides a mechanism to force certain routes not
|
|
// to get an automatic session where they don't have one already. This allows us
|
|
// to work around issues where we might overwrite a user's login cookie with one
|
|
// that is hidden by a `SameSite` setting.
|
|
//
|
|
// When registering a route with disableSessionAutostartForRoute, a callback
|
|
// should be provided that handles the case that a session is not available.
|
|
// This will be called as a standard middleware with (req, res, next) - calling
|
|
// next will continue and sett up a session as normal, otherwise the app can
|
|
// perform a different operation as usual
|
|
|
|
class SessionAutostartMiddleware {
|
|
constructor() {
|
|
this.middleware = this.middleware.bind(this)
|
|
this._cookieName = Settings.cookieName
|
|
this._noAutostartCallbacks = new Map()
|
|
}
|
|
|
|
static applyInitialMiddleware(router) {
|
|
const middleware = new SessionAutostartMiddleware()
|
|
router.sessionAutostartMiddleware = middleware
|
|
router.use(middleware.middleware)
|
|
}
|
|
|
|
disableSessionAutostartForRoute(route, method, callback) {
|
|
if (typeof callback !== 'function') {
|
|
throw new Error('callback not provided when disabling session autostart')
|
|
}
|
|
|
|
if (!this._noAutostartCallbacks[route]) {
|
|
this._noAutostartCallbacks[route] = new Map()
|
|
}
|
|
|
|
this._noAutostartCallbacks[route][method] = callback
|
|
}
|
|
|
|
applyDefaultPostGatewayForRoute(route) {
|
|
this.disableSessionAutostartForRoute(
|
|
route,
|
|
'POST',
|
|
SessionAutostartMiddleware.genericPostGatewayMiddleware
|
|
)
|
|
}
|
|
|
|
autostartCallbackForRequest(req) {
|
|
return (
|
|
this._noAutostartCallbacks[req.path] &&
|
|
this._noAutostartCallbacks[req.path][req.method]
|
|
)
|
|
}
|
|
|
|
middleware(req, res, next) {
|
|
if (!req.signedCookies[this._cookieName]) {
|
|
const callback = this.autostartCallbackForRequest(req)
|
|
if (callback) {
|
|
req.session = {
|
|
noSessionCallback: callback
|
|
}
|
|
}
|
|
}
|
|
|
|
next()
|
|
}
|
|
|
|
static invokeCallbackMiddleware(req, res, next) {
|
|
if (req.session.noSessionCallback) {
|
|
return req.session.noSessionCallback(req, res, next)
|
|
}
|
|
next()
|
|
}
|
|
|
|
static genericPostGatewayMiddleware(req, res, next) {
|
|
if (req.method !== 'POST') {
|
|
return next(
|
|
new Errors.OError({
|
|
message: 'post gateway invoked for non-POST request',
|
|
info: {
|
|
path: req.path,
|
|
method: req.method
|
|
}
|
|
})
|
|
)
|
|
}
|
|
|
|
if (req.body.viaGateway) {
|
|
return next()
|
|
}
|
|
|
|
res.render('general/post-gateway', { form_data: req.body })
|
|
}
|
|
}
|
|
|
|
module.exports = SessionAutostartMiddleware
|