diff --git a/app/server/lib/Authorizer.ts b/app/server/lib/Authorizer.ts index 13c29cdd..3637d17c 100644 --- a/app/server/lib/Authorizer.ts +++ b/app/server/lib/Authorizer.ts @@ -6,7 +6,7 @@ import {canEdit, canView, getWeakestRole, Role} from 'app/common/roles'; import {Document} from 'app/gen-server/entity/Document'; import {User} from 'app/gen-server/entity/User'; import {DocAuthKey, DocAuthResult, HomeDBManager} from 'app/gen-server/lib/HomeDBManager'; -import {getSessionProfiles, getSessionUser, getSignInStatus, linkOrgWithEmail, SessionObj, +import {forceSessionChange, getSessionProfiles, getSessionUser, getSignInStatus, linkOrgWithEmail, SessionObj, SessionUserObj, SignInStatus} from 'app/server/lib/BrowserSession'; import {RequestWithOrg} from 'app/server/lib/extractOrg'; import {COOKIE_MAX_AGE, getAllowedOrgForSessionID, getCookieDomain, @@ -188,6 +188,7 @@ export async function addRequestUser(dbManager: HomeDBManager, permitStore: IPer // If we haven't set a maxAge yet, set it now. if (session && session.cookie && !session.cookie.maxAge) { session.cookie.maxAge = COOKIE_MAX_AGE; + forceSessionChange(session); } // See if we have a profile linked with the active organization already. @@ -262,7 +263,7 @@ export function redirectToLoginUnconditionally( return async (req: Request, resp: Response, next: NextFunction) => { const mreq = req as RequestWithLogin; // Tell express-session to set our cookie: session handling post-login relies on it. - mreq.session.alive = true; + forceSessionChange(mreq.session); // Redirect to sign up if it doesn't look like the user has ever logged in (on // this browser) After logging in, `users` will be set in the session. Even after @@ -294,8 +295,9 @@ export function redirectToLogin( getSignUpRedirectUrl); return async (req: Request, resp: Response, next: NextFunction) => { const mreq = req as RequestWithLogin; - mreq.session.alive = true; // This will ensure that express-session will set our cookie - // if it hasn't already - we'll need it if we redirect. + // This will ensure that express-session will set our cookie if it hasn't already - + // we'll need it if we redirect. + forceSessionChange(mreq.session); if (mreq.userIsAuthorized) { return next(); } try { diff --git a/app/server/lib/BrowserSession.ts b/app/server/lib/BrowserSession.ts index 50926325..68df1bb6 100644 --- a/app/server/lib/BrowserSession.ts +++ b/app/server/lib/BrowserSession.ts @@ -45,8 +45,13 @@ export interface SessionObj { // This is optional since the session may already exist. orgToUser?: {[org: string]: number}; - // This gets set to encourage express-session to set a cookie. - alive?: boolean; + // This gets set to encourage express-session to set a cookie. Was a boolean in the past. + alive?: number; +} + +// Make an artificial change to a session to encourage express-session to set a cookie. +export function forceSessionChange(session: SessionObj) { + session.alive = Number(session.alive || 0) + 1; } // We expose a sign-in status in a cookie accessible to all subdomains, to assist in auto-signin. diff --git a/app/server/lib/FlexServer.ts b/app/server/lib/FlexServer.ts index d35fc509..310b6b58 100644 --- a/app/server/lib/FlexServer.ts +++ b/app/server/lib/FlexServer.ts @@ -21,6 +21,7 @@ import {attachAppEndpoint} from 'app/server/lib/AppEndpoint'; import {addRequestUser, getUser, getUserId, isSingleUserMode, redirectToLoginUnconditionally} from 'app/server/lib/Authorizer'; import {redirectToLogin, RequestWithLogin, signInStatusMiddleware} from 'app/server/lib/Authorizer'; +import {forceSessionChange} from 'app/server/lib/BrowserSession'; import * as Comm from 'app/server/lib/Comm'; import {create} from 'app/server/lib/create'; import {addDiscourseConnectEndpoints} from 'app/server/lib/DiscourseConnect'; @@ -593,7 +594,8 @@ export class FlexServer implements GristServer { // Create an endpoint for making cookies during testing. this.app.get('/test/session', async (req, res) => { - (req as any).session.alive = true; + const mreq = req as RequestWithLogin; + forceSessionChange(mreq.session); res.status(200).send(`Grist ${this.name} is alive and is interested in you.`); }); @@ -800,9 +802,9 @@ export class FlexServer implements GristServer { this: FlexServer, signUp: boolean|null, req: express.Request, resp: express.Response, ) { const mreq = req as RequestWithLogin; - mreq.session.alive = true; // This will ensure that express-session will set our cookie - // if it hasn't already - we'll need it when we come back - // from Cognito. + // This will ensure that express-session will set our cookie if it hasn't already - + // we'll need it when we come back from Cognito. + forceSessionChange(mreq.session); // Redirect to "/" on our requested hostname (in test env, this will redirect further) const next = req.protocol + '://' + req.get('host') + '/'; if (signUp === null) {