feat: Add session-based authentication for SSH connections using HTTP Basic auth and express.js
This commit is contained in:
parent
fe7248e056
commit
afe462b180
7 changed files with 240 additions and 36 deletions
35
app/app.js
35
app/app.js
|
@ -7,6 +7,8 @@ const express = require('express')
|
||||||
const socketIo = require('socket.io')
|
const socketIo = require('socket.io')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const bodyParser = require('body-parser')
|
const bodyParser = require('body-parser')
|
||||||
|
const session = require('express-session')
|
||||||
|
const sharedsession = require("express-socket.io-session")
|
||||||
const config = require('./config')
|
const config = require('./config')
|
||||||
const socketHandler = require('./socket')
|
const socketHandler = require('./socket')
|
||||||
const sshRoutes = require('./routes')
|
const sshRoutes = require('./routes')
|
||||||
|
@ -16,10 +18,19 @@ const sshRoutes = require('./routes')
|
||||||
* @returns {express.Application} The Express application instance
|
* @returns {express.Application} The Express application instance
|
||||||
*/
|
*/
|
||||||
function createApp() {
|
function createApp() {
|
||||||
var app = express();
|
const app = express();
|
||||||
|
|
||||||
// Resolve the correct path to the webssh2_client module
|
// Resolve the correct path to the webssh2_client module
|
||||||
var clientPath = path.resolve(__dirname, '..', 'node_modules', 'webssh2_client', 'client', 'public');
|
const clientPath = path.resolve(__dirname, '..', 'node_modules', 'webssh2_client', 'client', 'public');
|
||||||
|
|
||||||
|
// Set up session middleware
|
||||||
|
const sessionMiddleware = session({
|
||||||
|
secret: config.session.secret || 'webssh2_secret',
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: true,
|
||||||
|
name: config.session.name || 'webssh2.sid'
|
||||||
|
});
|
||||||
|
app.use(sessionMiddleware);
|
||||||
|
|
||||||
// Handle POST and GET parameters
|
// Handle POST and GET parameters
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
@ -31,7 +42,7 @@ function createApp() {
|
||||||
// Use the SSH routes
|
// Use the SSH routes
|
||||||
app.use('/ssh', sshRoutes);
|
app.use('/ssh', sshRoutes);
|
||||||
|
|
||||||
return app;
|
return { app, sessionMiddleware };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,13 +57,21 @@ function createServer(app) {
|
||||||
/**
|
/**
|
||||||
* Configures Socket.IO with the given server
|
* Configures Socket.IO with the given server
|
||||||
* @param {http.Server} server - The HTTP server instance
|
* @param {http.Server} server - The HTTP server instance
|
||||||
|
* @param {Function} sessionMiddleware - The session middleware
|
||||||
* @returns {import('socket.io').Server} The Socket.IO server instance
|
* @returns {import('socket.io').Server} The Socket.IO server instance
|
||||||
*/
|
*/
|
||||||
function configureSocketIO(server) {
|
function configureSocketIO(server, sessionMiddleware) {
|
||||||
return socketIo(server, {
|
const io = socketIo(server, {
|
||||||
path: '/ssh/socket.io',
|
path: '/ssh/socket.io',
|
||||||
cors: getCorsConfig()
|
cors: getCorsConfig()
|
||||||
})
|
});
|
||||||
|
|
||||||
|
// Share session with io sockets
|
||||||
|
io.use(sharedsession(sessionMiddleware, {
|
||||||
|
autoSave: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
return io;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,9 +99,9 @@ function setupSocketIOListeners(io) {
|
||||||
* @returns {Object} An object containing the server, io, and app instances
|
* @returns {Object} An object containing the server, io, and app instances
|
||||||
*/
|
*/
|
||||||
function startServer() {
|
function startServer() {
|
||||||
const app = createApp()
|
const { app, sessionMiddleware } = createApp()
|
||||||
const server = createServer(app)
|
const server = createServer(app)
|
||||||
const io = configureSocketIO(server)
|
const io = configureSocketIO(server, sessionMiddleware)
|
||||||
|
|
||||||
// Set up Socket.IO listeners
|
// Set up Socket.IO listeners
|
||||||
setupSocketIOListeners(io)
|
setupSocketIOListeners(io)
|
||||||
|
|
|
@ -6,6 +6,7 @@ const path = require('path')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const readConfig = require('read-config-ng')
|
const readConfig = require('read-config-ng')
|
||||||
const Ajv = require('ajv')
|
const Ajv = require('ajv')
|
||||||
|
const crypto = require('crypto')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} Config
|
* @typedef {Object} Config
|
||||||
|
@ -107,6 +108,10 @@ const defaultConfig = {
|
||||||
hmac: ['hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1'],
|
hmac: ['hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1'],
|
||||||
compress: ['none', 'zlib@openssh.com', 'zlib']
|
compress: ['none', 'zlib@openssh.com', 'zlib']
|
||||||
},
|
},
|
||||||
|
session: {
|
||||||
|
secret: generateSecureSecret(),
|
||||||
|
name: 'webssh2.sid'
|
||||||
|
},
|
||||||
serverlog: {
|
serverlog: {
|
||||||
client: false,
|
client: false,
|
||||||
server: false
|
server: false
|
||||||
|
@ -208,6 +213,14 @@ const configSchema = {
|
||||||
},
|
},
|
||||||
required: ['kex', 'cipher', 'hmac', 'compress']
|
required: ['kex', 'cipher', 'hmac', 'compress']
|
||||||
},
|
},
|
||||||
|
session: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
secret: { type: 'string' },
|
||||||
|
name: { type: 'string' }
|
||||||
|
},
|
||||||
|
required: ['secret', 'name']
|
||||||
|
},
|
||||||
serverlog: {
|
serverlog: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -271,19 +284,25 @@ function logError(message, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the configuration
|
* Loads and merges the configuration
|
||||||
* @returns {Config} The loaded configuration
|
* @returns {Config} The merged configuration
|
||||||
*/
|
*/
|
||||||
function loadConfig() {
|
function loadConfig() {
|
||||||
const configPath = getConfigPath()
|
const configPath = getConfigPath()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(configPath)) {
|
if (fs.existsSync(configPath)) {
|
||||||
const config = readConfigFile(configPath)
|
const providedConfig = readConfigFile(configPath)
|
||||||
return validateConfig(config)
|
|
||||||
|
// Deep merge the provided config with the default config
|
||||||
|
const mergedConfig = deepMerge(JSON.parse(JSON.stringify(defaultConfig)), providedConfig)
|
||||||
|
|
||||||
|
const validatedConfig = validateConfig(mergedConfig)
|
||||||
|
console.log('Merged and validated configuration')
|
||||||
|
return validatedConfig
|
||||||
} else {
|
} else {
|
||||||
logError(
|
logError(
|
||||||
'\n\nERROR: Missing config.json for webssh. Current config: ' +
|
'\n\nERROR: Missing config.json for webssh. Using default config: ' +
|
||||||
JSON.stringify(defaultConfig) +
|
JSON.stringify(defaultConfig) +
|
||||||
'\n\n See config.json.sample for details\n\n'
|
'\n\n See config.json.sample for details\n\n'
|
||||||
)
|
)
|
||||||
|
@ -291,7 +310,7 @@ function loadConfig() {
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logError(
|
logError(
|
||||||
'\n\nERROR: Missing config.json for webssh. Current config: ' +
|
'\n\nERROR: Problem loading config.json for webssh. Using default config: ' +
|
||||||
JSON.stringify(defaultConfig) +
|
JSON.stringify(defaultConfig) +
|
||||||
'\n\n See config.json.sample for details\n\n',
|
'\n\n See config.json.sample for details\n\n',
|
||||||
err
|
err
|
||||||
|
@ -300,6 +319,32 @@ function loadConfig() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a secure random session secret
|
||||||
|
* @returns {string} A random 32-byte hex string
|
||||||
|
*/
|
||||||
|
function generateSecureSecret() {
|
||||||
|
return crypto.randomBytes(32).toString('hex')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deep merges two objects
|
||||||
|
* @param {Object} target - The target object to merge into
|
||||||
|
* @param {Object} source - The source object to merge from
|
||||||
|
* @returns {Object} The merged object
|
||||||
|
*/
|
||||||
|
function deepMerge(target, source) {
|
||||||
|
for (const key in source) {
|
||||||
|
if (source.hasOwnProperty(key)) {
|
||||||
|
if (source[key] instanceof Object && !Array.isArray(source[key])) {
|
||||||
|
target[key] = deepMerge(target[key] || {}, source[key])
|
||||||
|
} else {
|
||||||
|
target[key] = source[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* The loaded configuration
|
* The loaded configuration
|
||||||
* @type {Config}
|
* @type {Config}
|
||||||
|
|
|
@ -22,12 +22,10 @@ function handleConnection(req, res, urlParams) {
|
||||||
path: '/ssh/socket.io'
|
path: '/ssh/socket.io'
|
||||||
},
|
},
|
||||||
ssh: {
|
ssh: {
|
||||||
host: connectionParams.host || '',
|
host: urlParams.host || '',
|
||||||
port: connectionParams.port || 22,
|
port: urlParams.port || 22
|
||||||
username: connectionParams.username || '',
|
|
||||||
password: connectionParams.password || ''
|
|
||||||
},
|
},
|
||||||
autoConnect: !!(connectionParams.host && connectionParams.username && connectionParams.password)
|
autoConnect: !!req.session.sshCredentials
|
||||||
};
|
};
|
||||||
|
|
||||||
// Read the client.htm file
|
// Read the client.htm file
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// server
|
// server
|
||||||
// /app/routes.js
|
// /app/routes.js
|
||||||
var express = require('express');
|
const express = require('express');
|
||||||
var router = express.Router();
|
const router = express.Router();
|
||||||
var handleConnection = require('./connectionHandler');
|
const handleConnection = require('./connectionHandler');
|
||||||
var basicAuth = require('basic-auth');
|
const basicAuth = require('basic-auth');
|
||||||
|
|
||||||
function auth(req, res, next) {
|
function auth(req, res, next) {
|
||||||
var credentials = basicAuth(req);
|
var credentials = basicAuth(req);
|
||||||
|
@ -11,7 +11,8 @@ function auth(req, res, next) {
|
||||||
res.setHeader('WWW-Authenticate', 'Basic realm="WebSSH2"');
|
res.setHeader('WWW-Authenticate', 'Basic realm="WebSSH2"');
|
||||||
return res.status(401).send('Authentication required.');
|
return res.status(401).send('Authentication required.');
|
||||||
}
|
}
|
||||||
req.sshCredentials = credentials;
|
// Store credentials in session
|
||||||
|
req.session.sshCredentials = credentials;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,11 +23,7 @@ router.get('/', function(req, res) {
|
||||||
|
|
||||||
// Scenario 2: Auth required
|
// Scenario 2: Auth required
|
||||||
router.get('/host/:host', auth, function(req, res) {
|
router.get('/host/:host', auth, function(req, res) {
|
||||||
handleConnection(req, res, {
|
handleConnection(req, res, { host: req.params.host });
|
||||||
host: req.params.host,
|
|
||||||
username: req.sshCredentials.name,
|
|
||||||
password: req.sshCredentials.pass
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
|
@ -59,6 +59,13 @@ function handleConnection(socket, config) {
|
||||||
*/
|
*/
|
||||||
function handleAuthentication(socket, creds, config) {
|
function handleAuthentication(socket, creds, config) {
|
||||||
console.log(`SOCKET AUTHENTICATE: ${socket.id}`)
|
console.log(`SOCKET AUTHENTICATE: ${socket.id}`)
|
||||||
|
const sessionCreds = socket.handshake.session.sshCredentials;
|
||||||
|
|
||||||
|
if (sessionCreds) {
|
||||||
|
creds.username = sessionCreds.name;
|
||||||
|
creds.password = sessionCreds.pass;
|
||||||
|
}
|
||||||
|
|
||||||
if (isValidCredentials(creds)) {
|
if (isValidCredentials(creds)) {
|
||||||
console.log(`SOCKET CREDENTIALS VALID: ${socket.id}`)
|
console.log(`SOCKET CREDENTIALS VALID: ${socket.id}`)
|
||||||
initializeConnection(socket, creds, config)
|
initializeConnection(socket, creds, config)
|
||||||
|
|
136
package-lock.json
generated
136
package-lock.json
generated
|
@ -325,6 +325,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
|
||||||
"integrity": "sha512-437oANT9tP582zZMwSvZGy2nmSeAb8DW2me3y+Uv1Wp2Rulr8Mqlyrv3E7MLxmsiaPSMMDmiDVzgE+e8zlMx9g=="
|
"integrity": "sha512-437oANT9tP582zZMwSvZGy2nmSeAb8DW2me3y+Uv1Wp2Rulr8Mqlyrv3E7MLxmsiaPSMMDmiDVzgE+e8zlMx9g=="
|
||||||
},
|
},
|
||||||
|
"base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||||
|
},
|
||||||
"base64id": {
|
"base64id": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
|
||||||
|
@ -466,6 +471,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"buffer": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"requires": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"buffer-from": {
|
"buffer-from": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||||
|
@ -748,6 +762,22 @@
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
||||||
"integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw=="
|
"integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw=="
|
||||||
},
|
},
|
||||||
|
"cookie-parser": {
|
||||||
|
"version": "1.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz",
|
||||||
|
"integrity": "sha512-YN/8nzPcK5o6Op4MIzAd4H4qUal5+3UaMhVIeaafFYL0pKvBQA/9Yhzo7ZwvBpjdGshsiTAb1+FC37M6RdPDFg==",
|
||||||
|
"requires": {
|
||||||
|
"cookie": "0.1.3",
|
||||||
|
"cookie-signature": "1.0.6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": {
|
||||||
|
"version": "0.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz",
|
||||||
|
"integrity": "sha512-mWkFhcL+HVG1KjeCjEBVJJ7s4sAGMLiBDFSDs4bzzvgLZt7rW8BhP6XV/8b1+pNvx/skd3yYxPuaF3Z6LlQzyw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"cookie-signature": {
|
"cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
|
@ -765,6 +795,14 @@
|
||||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"crc": {
|
||||||
|
"version": "3.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz",
|
||||||
|
"integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==",
|
||||||
|
"requires": {
|
||||||
|
"buffer": "^5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"create-error-class": {
|
"create-error-class": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
|
||||||
|
@ -1617,6 +1655,81 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"express-session": {
|
||||||
|
"version": "1.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz",
|
||||||
|
"integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==",
|
||||||
|
"requires": {
|
||||||
|
"cookie": "0.6.0",
|
||||||
|
"cookie-signature": "1.0.7",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"depd": "~2.0.0",
|
||||||
|
"on-headers": "~1.0.2",
|
||||||
|
"parseurl": "~1.3.3",
|
||||||
|
"safe-buffer": "5.2.1",
|
||||||
|
"uid-safe": "~2.1.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="
|
||||||
|
},
|
||||||
|
"cookie-signature": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"depd": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"express-socket.io-session": {
|
||||||
|
"version": "1.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-socket.io-session/-/express-socket.io-session-1.3.5.tgz",
|
||||||
|
"integrity": "sha512-ila9jN7Pu9OuNIDzkuW+ZChR2Y0TzyyFITT7xiOWCjuGCDUWioD382zqxI7HOaa8kIhfs3wTLOZMU9h6buuOFw==",
|
||||||
|
"requires": {
|
||||||
|
"cookie-parser": "~1.3.3",
|
||||||
|
"crc": "^3.3.0",
|
||||||
|
"debug": "~2.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"extend-shallow": {
|
"extend-shallow": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
|
||||||
|
@ -2182,6 +2295,11 @@
|
||||||
"safer-buffer": ">= 2.1.2 < 3"
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
|
||||||
|
},
|
||||||
"ignore": {
|
"ignore": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||||
|
@ -3079,6 +3197,11 @@
|
||||||
"ee-first": "1.1.1"
|
"ee-first": "1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"on-headers": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
|
||||||
|
},
|
||||||
"once": {
|
"once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
@ -3400,6 +3523,11 @@
|
||||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"random-bytes": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ=="
|
||||||
|
},
|
||||||
"range-parser": {
|
"range-parser": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||||
|
@ -4546,6 +4674,14 @@
|
||||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
|
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"uid-safe": {
|
||||||
|
"version": "2.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||||
|
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
|
||||||
|
"requires": {
|
||||||
|
"random-bytes": "~1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"unbox-primitive": {
|
"unbox-primitive": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
"body-parser": "^1.15.2",
|
"body-parser": "^1.15.2",
|
||||||
"debug": "~4.1.0",
|
"debug": "~4.1.0",
|
||||||
"express": "^4.14.1",
|
"express": "^4.14.1",
|
||||||
|
"express-session": "^1.18.0",
|
||||||
|
"express-socket.io-session": "^1.3.5",
|
||||||
"fs": "0.0.1-security",
|
"fs": "0.0.1-security",
|
||||||
"read-config-ng": "~3.0.7",
|
"read-config-ng": "~3.0.7",
|
||||||
"socket.io": "~2.2.0",
|
"socket.io": "~2.2.0",
|
||||||
|
|
Loading…
Reference in a new issue