fix: handle http basic auth in /ssh/host/
route
This commit is contained in:
parent
aa633aef0b
commit
1fc35f74da
3 changed files with 81 additions and 41 deletions
|
@ -7,56 +7,53 @@ var extend = require("util")._extend
|
||||||
function handleConnection(req, res, urlParams) {
|
function handleConnection(req, res, urlParams) {
|
||||||
urlParams = urlParams || {}
|
urlParams = urlParams || {}
|
||||||
|
|
||||||
// The path to the client directory of the webssh2 module.
|
const clientPath = path.resolve(
|
||||||
var clientPath = path.resolve(
|
|
||||||
__dirname,
|
__dirname,
|
||||||
"..",
|
'..',
|
||||||
"node_modules",
|
'node_modules',
|
||||||
"webssh2_client",
|
'webssh2_client',
|
||||||
"client",
|
'client',
|
||||||
"public"
|
'public'
|
||||||
)
|
)
|
||||||
|
|
||||||
// Combine URL parameters, query parameters, and form data
|
const connectionParams = extend({}, urlParams)
|
||||||
var connectionParams = extend({}, urlParams)
|
|
||||||
extend(connectionParams, req.query)
|
extend(connectionParams, req.query)
|
||||||
extend(connectionParams, req.body || {})
|
extend(connectionParams, req.body || {})
|
||||||
|
|
||||||
// Inject configuration
|
const sshCredentials = req.session.sshCredentials || {}
|
||||||
var config = {
|
|
||||||
|
const config = {
|
||||||
socket: {
|
socket: {
|
||||||
url: req.protocol + "://" + req.get("host"),
|
url: req.protocol + '://' + req.get('host'),
|
||||||
path: "/ssh/socket.io"
|
path: '/ssh/socket.io'
|
||||||
},
|
},
|
||||||
ssh: {
|
ssh: {
|
||||||
host: urlParams.host || "",
|
host: urlParams.host || sshCredentials.host || '',
|
||||||
port: urlParams.port || 22
|
port: urlParams.port || sshCredentials.port || 22,
|
||||||
|
username: sshCredentials.username || '',
|
||||||
|
password: sshCredentials.password || ''
|
||||||
},
|
},
|
||||||
autoConnect: !!req.session.sshCredentials
|
autoConnect: !!req.session.sshCredentials
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the client.htm file
|
|
||||||
fs.readFile(
|
fs.readFile(
|
||||||
path.join(clientPath, "client.htm"),
|
path.join(clientPath, 'client.htm'),
|
||||||
"utf8",
|
'utf8',
|
||||||
function (err, data) {
|
function (err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return res.status(500).send("Error loading client file")
|
return res.status(500).send('Error loading client file')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace relative paths with the correct path
|
|
||||||
var modifiedHtml = data.replace(
|
var modifiedHtml = data.replace(
|
||||||
/(src|href)="(?!http|\/\/)/g,
|
/(src|href)="(?!http|\/\/)/g,
|
||||||
'$1="/ssh/assets/'
|
'$1="/ssh/assets/'
|
||||||
)
|
)
|
||||||
|
|
||||||
// Inject the configuration into the HTML
|
|
||||||
modifiedHtml = modifiedHtml.replace(
|
modifiedHtml = modifiedHtml.replace(
|
||||||
"window.webssh2Config = null;",
|
'window.webssh2Config = null;',
|
||||||
"window.webssh2Config = " + JSON.stringify(config) + ";"
|
'window.webssh2Config = ' + JSON.stringify(config) + ';'
|
||||||
)
|
)
|
||||||
|
|
||||||
// Send the modified HTML
|
|
||||||
res.send(modifiedHtml)
|
res.send(modifiedHtml)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,34 +1,48 @@
|
||||||
// server
|
// server
|
||||||
// /app/routes.js
|
// /app/routes.js
|
||||||
const createDebug = require("debug")
|
const createDebug = require('debug')
|
||||||
const debug = createDebug("webssh2:routes")
|
const debug = createDebug('webssh2:routes')
|
||||||
const express = require("express")
|
const express = require('express')
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
const handleConnection = require("./connectionHandler")
|
const handleConnection = require('./connectionHandler')
|
||||||
const basicAuth = require("basic-auth")
|
const basicAuth = require('basic-auth')
|
||||||
|
|
||||||
function auth(req, res, next) {
|
function auth(req, res, next) {
|
||||||
debug("Authenticating user with HTTP Basic Auth")
|
debug('Authenticating user with HTTP Basic Auth')
|
||||||
var credentials = basicAuth(req)
|
var credentials = basicAuth(req)
|
||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
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.')
|
||||||
}
|
}
|
||||||
// Store credentials in session
|
// Store credentials in session
|
||||||
req.session.sshCredentials = credentials
|
req.session.sshCredentials = {
|
||||||
|
username: credentials.name,
|
||||||
|
password: credentials.pass
|
||||||
|
}
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scenario 1: No auth required, uses websocket authentication instead
|
// Scenario 1: No auth required, uses websocket authentication instead
|
||||||
router.get("/", function (req, res) {
|
router.get('/', function (req, res) {
|
||||||
debug("Accessed /ssh route")
|
debug('Accessed / route')
|
||||||
handleConnection(req, res)
|
handleConnection(req, res)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Scenario 2: Auth required, uses HTTP Basic Auth
|
// Scenario 2: Auth required, uses HTTP Basic Auth
|
||||||
router.get("/host/:host", auth, function (req, res) {
|
router.get('/host/:host', auth, function (req, res) {
|
||||||
debug(`Accessed /ssh/host/${req.params.host} route`)
|
debug(`Accessed /ssh/host/${req.params.host} route`)
|
||||||
handleConnection(req, res, { host: req.params.host })
|
handleConnection(req, res, { host: req.params.host })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Clear credentials route
|
||||||
|
router.post('/clear-credentials', function (req, res) {
|
||||||
|
req.session.sshCredentials = null
|
||||||
|
res.status(200).send('Credentials cleared.')
|
||||||
|
})
|
||||||
|
|
||||||
|
router.post("/force-reconnect", function (req, res) {
|
||||||
|
req.session.sshCredentials = null;
|
||||||
|
res.status(401).send("Authentication required.");
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|
|
@ -86,12 +86,27 @@ function handleConnection(socket, config) {
|
||||||
* @param {Object} config - The configuration object
|
* @param {Object} config - The configuration object
|
||||||
*/
|
*/
|
||||||
function handleAuthentication(socket, creds, config) {
|
function handleAuthentication(socket, creds, config) {
|
||||||
debug(`AUTHENTICATE: ${socket.id}, Host: ${creds.host}`)
|
// If reauth, creds from this function should take precedence
|
||||||
|
if (creds && isValidCredentials(creds)) {
|
||||||
|
// Store new credentials in session, overriding any existing ones
|
||||||
|
socket.handshake.session.sshCredentials = {
|
||||||
|
username: creds.username,
|
||||||
|
password: creds.password,
|
||||||
|
host: creds.host,
|
||||||
|
port: creds.port
|
||||||
|
}
|
||||||
|
|
||||||
if (isValidCredentials(creds)) {
|
// Save the session after updating
|
||||||
debug(`CREDENTIALS VALID: ${socket.id}, Host: ${creds.host}`)
|
socket.handshake.session.save((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`Failed to save session for ${socket.id}:`, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Proceed with connection initialization using the new credentials
|
||||||
initializeConnection(socket, creds, config)
|
initializeConnection(socket, creds, config)
|
||||||
} else {
|
} else {
|
||||||
|
// Handle invalid credentials scenario
|
||||||
debug(`CREDENTIALS INVALID: ${socket.id}, Host: ${creds.host}`)
|
debug(`CREDENTIALS INVALID: ${socket.id}, Host: ${creds.host}`)
|
||||||
socket.emit("authentication", {
|
socket.emit("authentication", {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -331,8 +346,22 @@ function handleConnection(socket, config) {
|
||||||
*/
|
*/
|
||||||
function handleReauth(socket) {
|
function handleReauth(socket) {
|
||||||
debug(`Reauthentication requested for ${socket.id}`)
|
debug(`Reauthentication requested for ${socket.id}`)
|
||||||
|
|
||||||
|
// Clear existing session credentials
|
||||||
|
socket.handshake.session.sshCredentials = null
|
||||||
|
|
||||||
|
// Save the session after modification
|
||||||
|
socket.handshake.session.save((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`Failed to save session for ${socket.id}:`, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify client to reauthenticate
|
||||||
socket.emit("authentication", { action: "reauth" })
|
socket.emit("authentication", { action: "reauth" })
|
||||||
|
|
||||||
|
// Close the current connection to enforce reauthentication
|
||||||
handleConnectionClose(socket)
|
handleConnectionClose(socket)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue