2019-10-31 22:09:54 +00:00
|
|
|
// Example of the server https is taken from here: https://engineering.circle.com/https-authorized-certs-with-node-js-315e548354a2
|
2022-10-05 11:13:20 +00:00
|
|
|
// Renew certificates:
|
|
|
|
// - openssl x509 -req -extfile server.cnf -days 9999 -passin "pass:password" -in server-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out server-crt.pem
|
|
|
|
// - openssl x509 -req -extfile client1.cnf -days 9999 -passin "pass:password" -in client1-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out client1-crt.pem
|
|
|
|
// - openssl x509 -req -extfile client2.cnf -days 9999 -passin "pass:password" -in client2-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out client2-crt.pem
|
|
|
|
// Verify certificates:
|
|
|
|
// - openssl verify -CAfile ca-crt.pem server-crt.pem
|
|
|
|
// - openssl verify -CAfile ca-crt.pem client1-crt.pem
|
|
|
|
// - openssl verify -CAfile ca-crt.pem client2-crt.pem
|
2019-10-31 22:09:54 +00:00
|
|
|
// Conversion of client1-crt.pem to certificate.pfx: https://stackoverflow.com/a/38408666/4637638
|
2022-10-05 11:13:20 +00:00
|
|
|
// - openssl pkcs12 -export -out certificate.pfx -inkey client1-key.pem -in client1-crt.pem -certfile ca-crt.pem
|
|
|
|
// - Overwrite certificate.pfx to example/test_assets/certificate.pfx
|
2022-10-06 13:13:31 +00:00
|
|
|
const express = require('express');
|
|
|
|
const http = require('http');
|
|
|
|
const https = require('https');
|
|
|
|
const cors = require('cors');
|
|
|
|
const auth = require('basic-auth');
|
|
|
|
const app = express();
|
|
|
|
const appHttps = express();
|
|
|
|
const appAuthBasic = express();
|
2019-10-31 22:09:54 +00:00
|
|
|
const fs = require('fs')
|
2019-11-05 02:44:22 +00:00
|
|
|
const path = require('path')
|
2021-03-18 16:24:13 +00:00
|
|
|
const bodyParser = require('body-parser');
|
|
|
|
const multiparty = require('multiparty');
|
2019-10-31 22:09:54 +00:00
|
|
|
|
2021-03-11 21:42:18 +00:00
|
|
|
var options = {
|
|
|
|
key: fs.readFileSync('server-key.pem'),
|
|
|
|
cert: fs.readFileSync('server-crt.pem'),
|
|
|
|
ca: fs.readFileSync('ca-crt.pem'),
|
2019-10-31 22:09:54 +00:00
|
|
|
requestCert: true,
|
2022-10-11 08:34:09 +00:00
|
|
|
rejectUnauthorized: false,
|
|
|
|
ciphers: "DEFAULT:@SECLEVEL=0"
|
2019-10-31 22:09:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
appHttps.get('/', (req, res) => {
|
2019-11-05 02:44:22 +00:00
|
|
|
console.log(JSON.stringify(req.headers))
|
2019-10-31 22:09:54 +00:00
|
|
|
const cert = req.connection.getPeerCertificate()
|
|
|
|
|
2019-11-25 00:42:27 +00:00
|
|
|
// The `req.client.authorized` flag will be true if the certificate is valid and was issued by a CA we white-listed
|
|
|
|
// earlier in `opts.ca`. We display the name of our user (CN = Common Name) and the name of the issuer, which is
|
|
|
|
// `localhost`.
|
2019-10-31 22:09:54 +00:00
|
|
|
|
|
|
|
if (req.client.authorized) {
|
2019-11-02 18:58:01 +00:00
|
|
|
res.send(`
|
2019-11-25 00:42:27 +00:00
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>Authorized</h1>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
`);
|
|
|
|
// They can still provide a certificate which is not accepted by us. Unfortunately, the `cert` object will be an empty
|
|
|
|
// object instead of `null` if there is no certificate at all, so we have to check for a known field rather than
|
|
|
|
// truthiness.
|
2019-10-31 22:09:54 +00:00
|
|
|
|
|
|
|
} else if (cert.subject) {
|
2019-11-25 00:42:27 +00:00
|
|
|
console.log(`Sorry ${cert.subject.CN}, certificates from ${cert.issuer.CN} are not welcome here.`);
|
|
|
|
res.status(403).send(`
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>Forbidden</h1>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
`);
|
|
|
|
// And last, they can come to us with no certificate at all:
|
2019-10-31 22:09:54 +00:00
|
|
|
} else {
|
2019-11-25 00:42:27 +00:00
|
|
|
console.log(`Sorry, but you need to provide a client certificate to continue.`)
|
|
|
|
res.status(401).send(`
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>Unauthorized</h1>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
`);
|
2019-10-31 22:09:54 +00:00
|
|
|
}
|
2019-11-02 18:58:01 +00:00
|
|
|
res.end()
|
|
|
|
})
|
|
|
|
|
2019-10-31 22:09:54 +00:00
|
|
|
// Let's create our HTTPS server and we're ready to go.
|
|
|
|
https.createServer(options, appHttps).listen(4433)
|
|
|
|
|
2019-11-25 00:42:27 +00:00
|
|
|
|
|
|
|
|
2019-10-31 22:09:54 +00:00
|
|
|
// Ensure this is before any other middleware or routes
|
|
|
|
appAuthBasic.use((req, res, next) => {
|
|
|
|
let user = auth(req)
|
|
|
|
|
2019-11-21 01:19:43 +00:00
|
|
|
if (user === undefined || user['name'] !== 'USERNAME' || user['pass'] !== 'PASSWORD') {
|
2019-10-31 22:09:54 +00:00
|
|
|
res.statusCode = 401
|
|
|
|
res.setHeader('WWW-Authenticate', 'Basic realm="Node"')
|
2019-11-21 01:19:43 +00:00
|
|
|
res.send(`
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>Unauthorized</h1>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
`);
|
|
|
|
res.end()
|
2019-10-31 22:09:54 +00:00
|
|
|
} else {
|
|
|
|
next()
|
|
|
|
}
|
2019-12-14 15:08:15 +00:00
|
|
|
});
|
2019-10-31 22:09:54 +00:00
|
|
|
|
2019-12-02 23:07:29 +00:00
|
|
|
appAuthBasic.use(express.static(__dirname + '/public'));
|
|
|
|
|
2019-10-31 22:09:54 +00:00
|
|
|
appAuthBasic.get("/", (req, res) => {
|
2019-11-05 02:44:22 +00:00
|
|
|
console.log(JSON.stringify(req.headers))
|
2019-10-31 22:09:54 +00:00
|
|
|
res.send(`
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
2019-11-21 01:19:43 +00:00
|
|
|
<h1>Authorized</h1>
|
2019-10-31 22:09:54 +00:00
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
`);
|
2019-11-04 00:39:23 +00:00
|
|
|
res.end()
|
2019-12-14 15:08:15 +00:00
|
|
|
});
|
2019-10-31 22:09:54 +00:00
|
|
|
|
2019-12-14 15:08:15 +00:00
|
|
|
appAuthBasic.get('/test-index', (req, res) => {
|
|
|
|
res.sendFile(__dirname + '/public/test-index.html');
|
|
|
|
});
|
|
|
|
|
|
|
|
appAuthBasic.listen(8081);
|
2019-11-04 00:39:23 +00:00
|
|
|
|
2019-11-25 00:42:27 +00:00
|
|
|
|
2019-11-05 02:44:22 +00:00
|
|
|
app.use(cors());
|
|
|
|
|
2021-03-18 16:24:13 +00:00
|
|
|
app.use(bodyParser.urlencoded({extended: false}));
|
2019-11-04 00:39:23 +00:00
|
|
|
// Parse JSON bodies (as sent by API clients)
|
2021-03-18 16:24:13 +00:00
|
|
|
app.use(bodyParser.json());
|
2019-11-04 00:39:23 +00:00
|
|
|
|
2019-12-02 23:07:29 +00:00
|
|
|
app.use(express.static(__dirname + '/public'));
|
|
|
|
|
2019-11-04 00:39:23 +00:00
|
|
|
app.get("/", (req, res) => {
|
2019-11-05 02:44:22 +00:00
|
|
|
console.log(JSON.stringify(req.headers))
|
2019-11-04 00:39:23 +00:00
|
|
|
res.send(`
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<p>HELLO</p>
|
|
|
|
</body>
|
2022-10-25 09:18:53 +00:00
|
|
|
</html>
|
|
|
|
`);
|
|
|
|
res.end()
|
|
|
|
})
|
|
|
|
|
|
|
|
app.get("/echo-headers", (req, res) => {
|
|
|
|
res.send(`
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<pre style="word-wrap: break-word; white-space: pre-wrap;">${JSON.stringify(req.headers)}</pre>
|
|
|
|
</body>
|
2019-11-04 00:39:23 +00:00
|
|
|
</html>
|
|
|
|
`);
|
|
|
|
res.end()
|
|
|
|
})
|
|
|
|
|
2019-12-14 15:08:15 +00:00
|
|
|
app.get('/test-index', (req, res) => {
|
2023-11-25 03:56:49 +00:00
|
|
|
res.sendFile(__dirname + '/public/test-index.html');
|
2019-12-14 15:08:15 +00:00
|
|
|
})
|
|
|
|
|
2019-11-04 00:39:23 +00:00
|
|
|
app.post("/test-post", (req, res) => {
|
2019-11-05 02:44:22 +00:00
|
|
|
console.log(JSON.stringify(req.headers))
|
2019-11-16 11:41:30 +00:00
|
|
|
console.log(JSON.stringify(req.body))
|
2019-11-04 00:39:23 +00:00
|
|
|
res.send(`
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<p>HELLO ${req.body.name}!</p>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
`);
|
|
|
|
res.end()
|
|
|
|
})
|
2019-11-05 02:44:22 +00:00
|
|
|
|
|
|
|
app.post("/test-ajax-post", (req, res) => {
|
2021-03-18 16:24:13 +00:00
|
|
|
console.log(JSON.stringify(req.headers));
|
|
|
|
if (req.headers["content-type"].indexOf("multipart/form-data;") === 0) {
|
|
|
|
const form = new multiparty.Form();
|
|
|
|
form.parse(req, function(err, fields, files) {
|
|
|
|
console.log(fields);
|
|
|
|
res.set("Content-Type", "application/json")
|
|
|
|
res.send(JSON.stringify({
|
|
|
|
"firstname": fields.firstname[0],
|
|
|
|
"lastname": fields.lastname[0],
|
|
|
|
}));
|
|
|
|
res.end();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
console.log(req.body);
|
|
|
|
res.set("Content-Type", "application/json")
|
|
|
|
res.send(JSON.stringify({
|
|
|
|
"firstname": req.body.firstname,
|
|
|
|
"lastname": req.body.lastname,
|
|
|
|
}));
|
|
|
|
res.end();
|
|
|
|
}
|
2019-11-05 02:44:22 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
app.get("/test-download-file", (req, res) => {
|
|
|
|
console.log(JSON.stringify(req.headers))
|
|
|
|
const filePath = path.join(__dirname, 'assets', 'flutter_logo.png');
|
|
|
|
const stat = fs.statSync(filePath);
|
|
|
|
const file = fs.readFileSync(filePath, 'binary');
|
|
|
|
res.setHeader('Content-Length', stat.size);
|
|
|
|
res.setHeader('Content-Type', 'image/png');
|
|
|
|
res.setHeader('Content-Disposition', 'attachment; filename=flutter_logo.png');
|
|
|
|
res.write(file, 'binary');
|
|
|
|
res.end();
|
|
|
|
})
|
|
|
|
|
2021-03-18 16:24:13 +00:00
|
|
|
app.listen(8082)
|
2022-10-06 13:13:31 +00:00
|
|
|
|
|
|
|
// Proxy server
|
|
|
|
http.createServer(function (req, res) {
|
|
|
|
res.setHeader('Content-type', 'text/html');
|
|
|
|
res.write(`
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>Proxy Works</h1>
|
|
|
|
<p id="url">${req.url}</p>
|
|
|
|
<p id="method">${req.method}</p>
|
|
|
|
<p id="headers">${JSON.stringify(req.headers)}</p>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
`);
|
|
|
|
res.end();
|
|
|
|
}).listen(8083);
|