Skip to content

Commit 1fc35f7

Browse files
committed
fix: handle http basic auth in /ssh/host/ route
1 parent aa633ae commit 1fc35f7

File tree

3 files changed

+81
-41
lines changed

3 files changed

+81
-41
lines changed

app/connectionHandler.js

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,56 +7,53 @@ var extend = require("util")._extend
77
function handleConnection(req, res, urlParams) {
88
urlParams = urlParams || {}
99

10-
// The path to the client directory of the webssh2 module.
11-
var clientPath = path.resolve(
10+
const clientPath = path.resolve(
1211
__dirname,
13-
"..",
14-
"node_modules",
15-
"webssh2_client",
16-
"client",
17-
"public"
12+
'..',
13+
'node_modules',
14+
'webssh2_client',
15+
'client',
16+
'public'
1817
)
1918

20-
// Combine URL parameters, query parameters, and form data
21-
var connectionParams = extend({}, urlParams)
19+
const connectionParams = extend({}, urlParams)
2220
extend(connectionParams, req.query)
2321
extend(connectionParams, req.body || {})
2422

25-
// Inject configuration
26-
var config = {
23+
const sshCredentials = req.session.sshCredentials || {}
24+
25+
const config = {
2726
socket: {
28-
url: req.protocol + "://" + req.get("host"),
29-
path: "/ssh/socket.io"
27+
url: req.protocol + '://' + req.get('host'),
28+
path: '/ssh/socket.io'
3029
},
3130
ssh: {
32-
host: urlParams.host || "",
33-
port: urlParams.port || 22
31+
host: urlParams.host || sshCredentials.host || '',
32+
port: urlParams.port || sshCredentials.port || 22,
33+
username: sshCredentials.username || '',
34+
password: sshCredentials.password || ''
3435
},
3536
autoConnect: !!req.session.sshCredentials
3637
}
3738

38-
// Read the client.htm file
3939
fs.readFile(
40-
path.join(clientPath, "client.htm"),
41-
"utf8",
40+
path.join(clientPath, 'client.htm'),
41+
'utf8',
4242
function (err, data) {
4343
if (err) {
44-
return res.status(500).send("Error loading client file")
44+
return res.status(500).send('Error loading client file')
4545
}
4646

47-
// Replace relative paths with the correct path
4847
var modifiedHtml = data.replace(
4948
/(src|href)="(?!http|\/\/)/g,
5049
'$1="/ssh/assets/'
5150
)
5251

53-
// Inject the configuration into the HTML
5452
modifiedHtml = modifiedHtml.replace(
55-
"window.webssh2Config = null;",
56-
"window.webssh2Config = " + JSON.stringify(config) + ";"
53+
'window.webssh2Config = null;',
54+
'window.webssh2Config = ' + JSON.stringify(config) + ';'
5755
)
5856

59-
// Send the modified HTML
6057
res.send(modifiedHtml)
6158
}
6259
)

app/routes.js

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,48 @@
11
// server
22
// /app/routes.js
3-
const createDebug = require("debug")
4-
const debug = createDebug("webssh2:routes")
5-
const express = require("express")
3+
const createDebug = require('debug')
4+
const debug = createDebug('webssh2:routes')
5+
const express = require('express')
66
const router = express.Router()
7-
const handleConnection = require("./connectionHandler")
8-
const basicAuth = require("basic-auth")
7+
const handleConnection = require('./connectionHandler')
8+
const basicAuth = require('basic-auth')
99

1010
function auth(req, res, next) {
11-
debug("Authenticating user with HTTP Basic Auth")
11+
debug('Authenticating user with HTTP Basic Auth')
1212
var credentials = basicAuth(req)
1313
if (!credentials) {
14-
res.setHeader("WWW-Authenticate", 'Basic realm="WebSSH2"')
15-
return res.status(401).send("Authentication required.")
14+
res.setHeader('WWW-Authenticate', 'Basic realm="WebSSH2"')
15+
return res.status(401).send('Authentication required.')
1616
}
1717
// Store credentials in session
18-
req.session.sshCredentials = credentials
18+
req.session.sshCredentials = {
19+
username: credentials.name,
20+
password: credentials.pass
21+
}
1922
next()
2023
}
2124

2225
// Scenario 1: No auth required, uses websocket authentication instead
23-
router.get("/", function (req, res) {
24-
debug("Accessed /ssh route")
26+
router.get('/', function (req, res) {
27+
debug('Accessed / route')
2528
handleConnection(req, res)
2629
})
2730

2831
// Scenario 2: Auth required, uses HTTP Basic Auth
29-
router.get("/host/:host", auth, function (req, res) {
32+
router.get('/host/:host', auth, function (req, res) {
3033
debug(`Accessed /ssh/host/${req.params.host} route`)
3134
handleConnection(req, res, { host: req.params.host })
3235
})
3336

37+
// Clear credentials route
38+
router.post('/clear-credentials', function (req, res) {
39+
req.session.sshCredentials = null
40+
res.status(200).send('Credentials cleared.')
41+
})
42+
43+
router.post("/force-reconnect", function (req, res) {
44+
req.session.sshCredentials = null;
45+
res.status(401).send("Authentication required.");
46+
});
47+
3448
module.exports = router

app/socket.js

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,27 @@ function handleConnection(socket, config) {
8686
* @param {Object} config - The configuration object
8787
*/
8888
function handleAuthentication(socket, creds, config) {
89-
debug(`AUTHENTICATE: ${socket.id}, Host: ${creds.host}`)
89+
// If reauth, creds from this function should take precedence
90+
if (creds && isValidCredentials(creds)) {
91+
// Store new credentials in session, overriding any existing ones
92+
socket.handshake.session.sshCredentials = {
93+
username: creds.username,
94+
password: creds.password,
95+
host: creds.host,
96+
port: creds.port
97+
}
98+
99+
// Save the session after updating
100+
socket.handshake.session.save((err) => {
101+
if (err) {
102+
console.error(`Failed to save session for ${socket.id}:`, err)
103+
}
104+
})
90105

91-
if (isValidCredentials(creds)) {
92-
debug(`CREDENTIALS VALID: ${socket.id}, Host: ${creds.host}`)
106+
// Proceed with connection initialization using the new credentials
93107
initializeConnection(socket, creds, config)
94108
} else {
109+
// Handle invalid credentials scenario
95110
debug(`CREDENTIALS INVALID: ${socket.id}, Host: ${creds.host}`)
96111
socket.emit("authentication", {
97112
success: false,
@@ -331,8 +346,22 @@ function handleConnection(socket, config) {
331346
*/
332347
function handleReauth(socket) {
333348
debug(`Reauthentication requested for ${socket.id}`)
334-
socket.emit("authentication", { action: "reauth" })
335-
handleConnectionClose(socket)
349+
350+
// Clear existing session credentials
351+
socket.handshake.session.sshCredentials = null
352+
353+
// Save the session after modification
354+
socket.handshake.session.save((err) => {
355+
if (err) {
356+
console.error(`Failed to save session for ${socket.id}:`, err)
357+
}
358+
359+
// Notify client to reauthenticate
360+
socket.emit("authentication", { action: "reauth" })
361+
362+
// Close the current connection to enforce reauthentication
363+
handleConnectionClose(socket)
364+
})
336365
}
337366

338367
/**

0 commit comments

Comments
 (0)