mirror of
https://github.com/lovasoa/whitebophir
synced 2024-11-10 06:24:17 +00:00
Authenticates websockets & adds jwt test env
This commit is contained in:
parent
4ba291d86a
commit
1bdcdad3e3
7 changed files with 44 additions and 15 deletions
|
@ -79,6 +79,12 @@ See instructions on our Wiki about [how to setup a reverse proxy for WBO](https:
|
|||
WBO is available in multiple languages. The translations are stored in [`server/translations.json`](./server/translations.json).
|
||||
If you feel like contributing to this collaborative project, you can [translate WBO into your own language](https://github.com/lovasoa/whitebophir/wiki/How-to-translate-WBO-into-your-own-language).
|
||||
|
||||
## Authentication
|
||||
|
||||
WBO supports authentication with a JWT. This should be passed in as a query with the key `token`, eg, `http://myboard.com/boards/test?token={token}`
|
||||
|
||||
The `AUTH_SECRET_KEY` variable in [`configuration.js`](./server/configuration.js) should filled with the secret key for the JWT.
|
||||
|
||||
## Configuration
|
||||
|
||||
When you start a WBO server, it loads its configuration from several environment variables.
|
||||
|
|
|
@ -62,8 +62,12 @@ Tools.connect = function () {
|
|||
self.socket = null;
|
||||
}
|
||||
|
||||
var url = new URL(window.location);
|
||||
var params = new URLSearchParams(url.search);
|
||||
var token = params.get("token");
|
||||
|
||||
this.socket = io.connect('', {
|
||||
"query": "token=" + token,
|
||||
"path": window.location.pathname.split("/boards/")[0] + "/socket.io",
|
||||
"reconnection": true,
|
||||
"reconnectionDelay": 100, //Make the xhr connections as fast as possible
|
||||
|
|
|
@ -24,7 +24,11 @@ module.exports = {
|
|||
"args": ["-headless"]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
"jwt": {
|
||||
"globals": {
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.5mhBHqs5_DTLdINd9p5m7ZJ6XD0Xc55kIaCRY5r6HRA"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"start": "node ./server/server.js",
|
||||
"test": "nightwatch tests"
|
||||
"test": "nightwatch tests && nightwatch tests --env jwt"
|
||||
},
|
||||
"main": "./server/server.js",
|
||||
"repository": {
|
||||
|
|
|
@ -104,13 +104,9 @@ function validateBoardName(boardName) {
|
|||
*/
|
||||
function userHasPermission(url) {
|
||||
if(config.AUTH_SECRET_KEY != "") {
|
||||
if(url.searchParams.get("token")) {
|
||||
var token = url.searchParams.get("token");
|
||||
try {
|
||||
jsonwebtoken.verify(token, config.AUTH_SECRET_KEY);
|
||||
} catch(error) { // Token not valid
|
||||
throw new Error(error)
|
||||
}
|
||||
var token = url.searchParams.get("token");
|
||||
if(token) {
|
||||
jsonwebtoken.verify(token, config.AUTH_SECRET_KEY);
|
||||
} else { // Error out as no token provided
|
||||
throw new Error("No token provided");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
var iolib = require("socket.io"),
|
||||
{ log, gauge, monitorFunction } = require("./log.js"),
|
||||
BoardData = require("./boardData.js").BoardData,
|
||||
config = require("./configuration");
|
||||
config = require("./configuration"),
|
||||
jsonwebtoken = require("jsonwebtoken");
|
||||
|
||||
/** Map from name to *promises* of BoardData
|
||||
@type {{[boardName: string]: Promise<BoardData>}}
|
||||
|
@ -29,6 +30,20 @@ function noFail(fn) {
|
|||
|
||||
function startIO(app) {
|
||||
io = iolib(app);
|
||||
if (config.AUTH_SECRET_KEY) {
|
||||
// Middleware to check for valid jwt
|
||||
io.use(function(socket, next) {
|
||||
if(socket.handshake.query && socket.handshake.query.token) {
|
||||
jsonwebtoken.verify(socket.handshake.query.token, config.AUTH_SECRET_KEY, function(err, decoded) {
|
||||
if(err) return next(new Error("Authentication error: Invalid JWT"));
|
||||
socket.decoded = decoded;
|
||||
next();
|
||||
})
|
||||
} else {
|
||||
next(new Error("Authentication error: No jwt provided"));
|
||||
}
|
||||
});
|
||||
}
|
||||
io.on("connection", noFail(handleSocketConnection));
|
||||
return io;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,16 @@ const path = require("path");
|
|||
const PORT = 8487
|
||||
const SERVER = 'http://localhost:' + PORT;
|
||||
|
||||
let wbo, data_path;
|
||||
let wbo, data_path, tokenQuery;
|
||||
|
||||
async function beforeEach(browser, done) {
|
||||
data_path = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'wbo-test-data-'));
|
||||
process.env["PORT"] = PORT;
|
||||
process.env["WBO_HISTORY_DIR"] = data_path;
|
||||
if(browser.globals.token) {
|
||||
process.env["AUTH_SECRET_KEY"] = "test";
|
||||
tokenQuery = "token=" + browser.globals.token;
|
||||
}
|
||||
console.log("Launching WBO in " + data_path);
|
||||
wbo = require("../server/server.js");
|
||||
done();
|
||||
|
@ -51,7 +55,7 @@ function testPencil(browser) {
|
|||
.refresh()
|
||||
.waitForElementVisible("path[d='M 100 200 L 100 200 C 100 200 300 400 300 400'][stroke='#123456']")
|
||||
.assert.visible("path[d='M 0 0 L 0 0 C 0 0 40 120 90 120 C 140 120 180 0 180 0'][stroke='#abcdef']")
|
||||
.url(SERVER + '/preview/anonymous')
|
||||
.url(SERVER + '/preview/anonymous?' + tokenQuery)
|
||||
.waitForElementVisible("path[d='M 100 200 L 100 200 C 100 200 300 400 300 400'][stroke='#123456']")
|
||||
.assert.visible("path[d='M 0 0 L 0 0 C 0 0 40 120 90 120 C 140 120 180 0 180 0'][stroke='#abcdef']")
|
||||
.back()
|
||||
|
@ -92,15 +96,15 @@ function testCursor(browser) {
|
|||
}
|
||||
|
||||
function testBoard(browser) {
|
||||
var page = browser.url(SERVER + '/boards/anonymous?lang=fr')
|
||||
var page = browser.url(SERVER + '/boards/anonymous?lang=fr&' + tokenQuery)
|
||||
.waitForElementVisible('.tool[title ~= Crayon]') // pencil
|
||||
page = testPencil(page);
|
||||
page = testCircle(page);
|
||||
page = testCursor(page);
|
||||
|
||||
// test hideMenu
|
||||
browser.url(SERVER + '/boards/anonymous?lang=fr&hideMenu=true').waitForElementNotVisible('#menu');
|
||||
browser.url(SERVER + '/boards/anonymous?lang=fr&hideMenu=false').waitForElementVisible('#menu');
|
||||
browser.url(SERVER + '/boards/anonymous?lang=fr&hideMenu=true&' + tokenQuery).waitForElementNotVisible('#menu');
|
||||
browser.url(SERVER + '/boards/anonymous?lang=fr&hideMenu=false&' + tokenQuery).waitForElementVisible('#menu');
|
||||
|
||||
page.end();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue