mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
@ -70,7 +70,7 @@ perUserBasicAuth: false
|
|||||||
## Set to a positive number to expire session after a certain time of inactivity
|
## Set to a positive number to expire session after a certain time of inactivity
|
||||||
## Set to 0 to expire session when the browser is closed
|
## Set to 0 to expire session when the browser is closed
|
||||||
## Set to a negative number to disable session expiration
|
## Set to a negative number to disable session expiration
|
||||||
sessionTimeout: 86400
|
sessionTimeout: -1
|
||||||
# Used to sign session cookies. Will be auto-generated if not set
|
# Used to sign session cookies. Will be auto-generated if not set
|
||||||
cookieSecret: ''
|
cookieSecret: ''
|
||||||
# Disable CSRF protection - NOT RECOMMENDED
|
# Disable CSRF protection - NOT RECOMMENDED
|
||||||
|
10
package-lock.json
generated
10
package-lock.json
generated
@ -26,7 +26,7 @@
|
|||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"cookie-session": "^2.1.0",
|
"cookie-session": "^2.1.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"csrf-csrf": "^2.2.3",
|
"csrf-sync": "^4.0.3",
|
||||||
"diff-match-patch": "^1.0.5",
|
"diff-match-patch": "^1.0.5",
|
||||||
"dompurify": "^3.1.7",
|
"dompurify": "^3.1.7",
|
||||||
"droll": "^0.2.1",
|
"droll": "^0.2.1",
|
||||||
@ -2987,10 +2987,10 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/csrf-csrf": {
|
"node_modules/csrf-sync": {
|
||||||
"version": "2.2.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/csrf-csrf/-/csrf-csrf-2.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/csrf-sync/-/csrf-sync-4.0.3.tgz",
|
||||||
"integrity": "sha512-LuhBmy5RfRmEfeqeYqgaAuS1eDpVtKZB/Eiec9xiKQLBynJxrGVRdM2yRT/YMl1Njo/yKh2L9AYsIwSlTPnx2A==",
|
"integrity": "sha512-wXzltBBzt/7imzDt6ZT7G/axQG7jo4Sm0uXDUzFY8hR59qhDHdjqpW2hojS4oAVIZDzwlMQloIVCTJoDDh0wwA==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"http-errors": "^2.0.0"
|
"http-errors": "^2.0.0"
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"cookie-session": "^2.1.0",
|
"cookie-session": "^2.1.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"csrf-csrf": "^2.2.3",
|
"csrf-sync": "^4.0.3",
|
||||||
"diff-match-patch": "^1.0.5",
|
"diff-match-patch": "^1.0.5",
|
||||||
"dompurify": "^3.1.7",
|
"dompurify": "^3.1.7",
|
||||||
"droll": "^0.2.1",
|
"droll": "^0.2.1",
|
||||||
|
41
server.js
41
server.js
@ -18,10 +18,9 @@ import { hideBin } from 'yargs/helpers';
|
|||||||
|
|
||||||
// express/server related library imports
|
// express/server related library imports
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import { doubleCsrf } from 'csrf-csrf';
|
import { csrfSync } from 'csrf-sync';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import compression from 'compression';
|
import compression from 'compression';
|
||||||
import cookieParser from 'cookie-parser';
|
|
||||||
import cookieSession from 'cookie-session';
|
import cookieSession from 'cookie-session';
|
||||||
import multer from 'multer';
|
import multer from 'multer';
|
||||||
import responseTime from 'response-time';
|
import responseTime from 'response-time';
|
||||||
@ -40,7 +39,6 @@ util.inspect.defaultOptions.depth = 4;
|
|||||||
import { loadPlugins } from './src/plugin-loader.js';
|
import { loadPlugins } from './src/plugin-loader.js';
|
||||||
import {
|
import {
|
||||||
initUserStorage,
|
initUserStorage,
|
||||||
getCsrfSecret,
|
|
||||||
getCookieSecret,
|
getCookieSecret,
|
||||||
getCookieSessionName,
|
getCookieSessionName,
|
||||||
getAllEnabledUsers,
|
getAllEnabledUsers,
|
||||||
@ -347,8 +345,8 @@ if (enableCorsProxy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSessionCookieAge() {
|
function getSessionCookieAge() {
|
||||||
// Defaults to 24 hours in seconds if not set
|
// Defaults to "no expiration" if not set
|
||||||
const configValue = getConfigValue('sessionTimeout', 24 * 60 * 60);
|
const configValue = getConfigValue('sessionTimeout', -1);
|
||||||
|
|
||||||
// Convert to milliseconds
|
// Convert to milliseconds
|
||||||
if (configValue > 0) {
|
if (configValue > 0) {
|
||||||
@ -377,27 +375,34 @@ app.use(setUserDataMiddleware);
|
|||||||
|
|
||||||
// CSRF Protection //
|
// CSRF Protection //
|
||||||
if (!disableCsrf) {
|
if (!disableCsrf) {
|
||||||
const COOKIES_SECRET = getCookieSecret();
|
const csrfSyncProtection = csrfSync({
|
||||||
|
getTokenFromState: (req) => {
|
||||||
const { generateToken, doubleCsrfProtection } = doubleCsrf({
|
if (!req.session) {
|
||||||
getSecret: getCsrfSecret,
|
console.error('(CSRF error) getTokenFromState: Session object not initialized');
|
||||||
cookieName: 'X-CSRF-Token',
|
return;
|
||||||
cookieOptions: {
|
}
|
||||||
sameSite: 'strict',
|
return req.session.csrfToken;
|
||||||
secure: false,
|
|
||||||
},
|
},
|
||||||
size: 64,
|
getTokenFromRequest: (req) => {
|
||||||
getTokenFromRequest: (req) => req.headers['x-csrf-token'],
|
return req.headers['x-csrf-token']?.toString();
|
||||||
|
},
|
||||||
|
storeTokenInState: (req, token) => {
|
||||||
|
if (!req.session) {
|
||||||
|
console.error('(CSRF error) storeTokenInState: Session object not initialized');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
req.session.csrfToken = token;
|
||||||
|
},
|
||||||
|
size: 32,
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/csrf-token', (req, res) => {
|
app.get('/csrf-token', (req, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
'token': generateToken(res, req),
|
'token': csrfSyncProtection.generateToken(req),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(cookieParser(COOKIES_SECRET));
|
app.use(csrfSyncProtection.csrfSynchronisedProtection);
|
||||||
app.use(doubleCsrfProtection);
|
|
||||||
} else {
|
} else {
|
||||||
console.warn('\nCSRF protection is disabled. This will make your server vulnerable to CSRF attacks.\n');
|
console.warn('\nCSRF protection is disabled. This will make your server vulnerable to CSRF attacks.\n');
|
||||||
app.get('/csrf-token', (req, res) => {
|
app.get('/csrf-token', (req, res) => {
|
||||||
|
@ -23,6 +23,7 @@ router.post('/logout', async (request, response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
request.session.handle = null;
|
request.session.handle = null;
|
||||||
|
request.session.csrfToken = null;
|
||||||
request.session = null;
|
request.session = null;
|
||||||
return response.sendStatus(204);
|
return response.sendStatus(204);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
Reference in New Issue
Block a user