Skip to content

feat: Update passport #2806

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: alpha
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions Parse-Dashboard/Authentication.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ const bcrypt = require('bcryptjs');
const csrf = require('csurf');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const OTPAuth = require('otpauth')
const OTPAuth = require('otpauth');
const session = require('express-session');

/**
* Constructor for Authentication class
Expand Down Expand Up @@ -55,34 +56,46 @@ function initialize(app, options) {

const cookieSessionSecret = options.cookieSessionSecret || require('crypto').randomBytes(64).toString('hex');
const cookieSessionMaxAge = options.cookieSessionMaxAge;

app.use(require('connect-flash')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('cookie-session')({
key : 'parse_dash',
secret : cookieSessionSecret,
maxAge : cookieSessionMaxAge

app.use(session({
name: 'parse_dash',
secret: cookieSessionSecret,
resave: false,
saveUninitialized: false,
cookie: {
maxAge: cookieSessionMaxAge,
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax'
}
}));
Comment on lines +63 to 74
Copy link

@coderabbitai coderabbitai bot May 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Improved session configuration with security enhancements.

The express-session configuration includes good security practices:

  • Named session to avoid conflicts
  • Explicit resave and saveUninitialized settings
  • Enhanced cookie security settings (httpOnly, secure in production, sameSite: 'lax')

However, the default in-memory session store isn't production-ready as it will leak memory in long-running applications.

Consider adding a production-ready session store like Redis or MongoDB for production environments:

app.use(session({
  name: 'parse_dash',
  secret: cookieSessionSecret,
  resave: false,
  saveUninitialized: false,
+  store: process.env.NODE_ENV === 'production' 
+    ? new RedisStore({ /* redis options */ }) 
+    : null, // Use memory store in development
  cookie: {
    maxAge: cookieSessionMaxAge,
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax'
  }
}));

🌐 Web query:

What is the best session store for express-session in production?

💡 Result:

When choosing a session store for express-session in production, it's crucial to avoid the default MemoryStore, which is explicitly not recommended for production environments. The default MemoryStore will leak memory and won't scale beyond a single process[4].

Recommended Session Stores

Redis is widely considered one of the best options for session storage in production environments. It's a high-performance, in-memory store that's well-suited for production. Many developers prefer Redis because it offers:

  • High performance and speed
  • Persistence capabilities
  • Scalability across multiple processes
  • Built-in TTL (time-to-live) functionality

To implement Redis with express-session, you would:

const redis = require('redis');
const session = require('express-session');
let RedisStore = require('connect-redis')(session);
let redisClient = redis.createClient();

app.use(
  session({
    secret: ['veryimportantsecret','notsoimportantsecret','highlyprobablysecret'],
    name: "secretname",
    cookie: {
      httpOnly: true,
      secure: true,
      sameSite: true,
      maxAge: 600000 // Time in milliseconds
    },
    store: new RedisStore({ client: redisClient, ttl: 86400 }),
    resave: false
  })
);
```[5]

## Other Production-Ready Options

If Redis doesn't suit your needs, there are numerous other production-ready session stores compatible with express-session:

- **Database-based stores**:
  - MongoDB (connect-mongo)
  - MySQL (express-mysql-session)
  - PostgreSQL (via various adapters)
  - Oracle (express-oracle-session)

- **Other in-memory stores**:
  - DynamoDB (dynamodb-store)
  - Firestore (firestore-store)
  - Hazelcast (hazelcast-store)

- **ORM-based stores**:
  - TypeORM (connect-typeorm)
  - Sequelize

Express-session's documentation lists many compatible session stores that you can choose from depending on your application's specific requirements[1][7].

## Selection Criteria

When selecting a session store for production, consider:

1. **Performance needs**: How fast do you need session retrieval to be?
2. **Scalability requirements**: Will your application run on multiple servers?
3. **Persistence needs**: Do you need sessions to survive server restarts?
4. **Existing infrastructure**: It often makes sense to use technology you're already familiar with or have deployed
5. **Security considerations**: Some stores offer additional security features

The key is choosing a store that integrates well with your existing stack while providing the performance and reliability your application requires.

Citations:

- 1: https://expressjs.com/en/resources/middleware/session.html
- 2: https://supertokens.com/blog/should-you-use-express-session-for-your-production-app
- 3: https://expressjs.com/en/advanced/best-practice-security.html
- 4: https://github.com/expressjs/session/issues/556
- 5: https://dev.to/jscrambler/best-practices-for-secure-session-management-in-node-3f01
- 6: https://github.com/expressjs/session/issues/143
- 7: https://www.youtube.com/watch?v=T9MsNRI5T-A
- 8: https://expressjs.com/en/advanced/best-practice-performance.html

---



</details>

**Add a production-ready session store (Redis) to avoid MemoryStore**  

The default MemoryStore in express-session isn’t suitable for production—it will leak memory and won’t scale across processes. Integrate a Redis-backed store for high performance, persistence, and scalability:

• File: Parse-Dashboard/Authentication.js (lines 63–74)  
• Install dependencies: `redis` and `connect-redis`  
• Initialize Redis client and store at the top of the file  
• Configure `store` only in production  

```diff
 // at the top of Parse-Dashboard/Authentication.js
+const redis = require('redis');
+const RedisStore = require('connect-redis')(session);
+const redisClient = redis.createClient({
+  // configure host, port, password, etc., if needed
+});

 app.use(
   session({
     name: 'parse_dash',
     secret: cookieSessionSecret,
     resave: false,
     saveUninitialized: false,
+    store: process.env.NODE_ENV === 'production'
+      ? new RedisStore({
+          client: redisClient,
+          ttl: cookieSessionMaxAge / 1000 // convert ms to seconds
+        })
+      : undefined,
     cookie: {
       maxAge: cookieSessionMaxAge,
       httpOnly: true,
       secure: process.env.NODE_ENV === 'production',
       sameSite: 'lax'
     }
   })
 );

This ensures session data persists outside of your app process and scales in production environments.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
app.use(session({
name: 'parse_dash',
secret: cookieSessionSecret,
resave: false,
saveUninitialized: false,
cookie: {
maxAge: cookieSessionMaxAge,
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax'
}
}));
// at the top of Parse-Dashboard/Authentication.js
const redis = require('redis');
const RedisStore = require('connect-redis')(session);
const redisClient = redis.createClient({
// configure host, port, password, etc., if needed
});
app.use(
session({
name: 'parse_dash',
secret: cookieSessionSecret,
resave: false,
saveUninitialized: false,
store: process.env.NODE_ENV === 'production'
? new RedisStore({
client: redisClient,
ttl: cookieSessionMaxAge / 1000 // convert ms to seconds
})
: undefined,
cookie: {
maxAge: cookieSessionMaxAge,
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax'
}
})
);
🤖 Prompt for AI Agents (early access)
In Parse-Dashboard/Authentication.js around lines 63 to 74, the current
express-session setup uses the default MemoryStore, which is not suitable for
production due to memory leaks and lack of scalability. To fix this, install the
'redis' and 'connect-redis' packages, then initialize a Redis client and
RedisStore at the top of the file. Modify the session middleware to use the
RedisStore as the session store only when in production environment, keeping the
existing configuration for development. This change will ensure session
persistence and scalability in production.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, the default in-memory session store isn't production-ready as it will leak memory in long-running applications.

@dblythy any action needed here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!


app.use(passport.initialize());
app.use(passport.session());

app.post('/login',
csrf(),
(req,res,next) => {
(req, res, next) => {
let redirect = 'apps';
if (req.body.redirect) {
redirect = req.body.redirect.charAt(0) === '/' ? req.body.redirect.substring(1) : req.body.redirect
redirect = req.body.redirect.charAt(0) === '/' ? req.body.redirect.substring(1) : req.body.redirect;
}
return passport.authenticate('local', {
successRedirect: `${self.mountPath}${redirect}`,
failureRedirect: `${self.mountPath}login${req.body.redirect ? `?redirect=${req.body.redirect}` : ''}`,
failureFlash : true
})(req, res, next)
failureFlash: true
})(req, res, next);
},
);

app.get('/logout', function(req, res){
req.logout();
res.redirect(`${self.mountPath}login`);
app.get('/logout', function(req, res, next) {
req.logout(function(err) {
if (err) { return next(err); }
res.redirect(`${self.mountPath}login`);
});
});
}

Expand Down
168 changes: 86 additions & 82 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@
"body-parser": "2.2.0",
"commander": "13.1.0",
"connect-flash": "0.1.1",
"cookie-session": "2.1.0",
"copy-to-clipboard": "3.3.3",
"core-js": "3.41.0",
"csurf": "1.11.0",
"express": "4.21.2",
"express-session": "1.18.1",
"graphiql": "2.0.8",
"graphql": "16.11.0",
"immutable": "5.1.2",
Expand All @@ -55,7 +55,7 @@
"otpauth": "8.0.3",
"package-json": "7.0.0",
"parse": "3.5.1",
"passport": "0.5.3",
"passport": "0.7.0",
"passport-local": "1.0.0",
"prismjs": "1.30.0",
"prop-types": "15.8.1",
Expand Down
Loading