mirror of
https://github.com/status-im/embark-area-51.git
synced 2025-01-12 06:54:58 +00:00
b654fdecd8
The authenticators request hash algorithm produced different hashes than on the client, because client-side hash-request don't include the query parameters of a URL. This causes authentication issues when sending any requests with query parameters. This commit ensures we ignore them on the server as well.
96 lines
2.8 KiB
JavaScript
96 lines
2.8 KiB
JavaScript
const uuid = require('uuid/v1');
|
|
const utils = require("../../utils/utils.js")
|
|
const keccak = require('keccakjs');
|
|
|
|
const ERROR_OBJ = {error: __('Wrong authentication token. Get your token from the Embark console by typing `token`')};
|
|
|
|
class Authenticator {
|
|
constructor(embark, _options) {
|
|
this.authToken = uuid();
|
|
this.embark = embark;
|
|
this.logger = embark.logger;
|
|
this.events = embark.events;
|
|
|
|
this.registerCalls();
|
|
this.registerEvents();
|
|
}
|
|
|
|
generateRequestHash(req) {
|
|
let cnonce = req.headers['x-embark-cnonce'];
|
|
let hash = new keccak();
|
|
let url = req.url;
|
|
let queryParamIndex = url.indexOf('?');
|
|
url = url.substring(0, queryParamIndex !== -1 ? queryParamIndex : url.length)
|
|
|
|
hash.update(cnonce);
|
|
hash.update(this.authToken);
|
|
hash.update(req.method);
|
|
hash.update(url);
|
|
return hash.digest('hex');
|
|
}
|
|
|
|
registerCalls() {
|
|
let self = this;
|
|
|
|
this.embark.registerAPICall(
|
|
'post',
|
|
'/embark-api/authenticate',
|
|
(req, res) => {
|
|
let hash = self.generateRequestHash(req);
|
|
if(hash !== req.headers['x-embark-request-hash']) {
|
|
this.logger.warn(__('Someone tried and failed to authenticate to the backend'));
|
|
this.logger.warn(__('- User-Agent: %s', req.headers['user-agent']));
|
|
this.logger.warn(__('- Referer: %s', req.headers.referer));
|
|
return res.send(ERROR_OBJ);
|
|
}
|
|
res.send({});
|
|
}
|
|
);
|
|
|
|
this.embark.registerConsoleCommand((cmd, _options) => {
|
|
return {
|
|
match: () => cmd === "token",
|
|
process: (callback) => {
|
|
callback(null, __('Your authentication token: %s \nYou can use the command `copytoken` to copy the authentication token to your clipboard', this.authToken));
|
|
}
|
|
};
|
|
});
|
|
|
|
this.embark.registerConsoleCommand((cmd, _options) => {
|
|
return {
|
|
match: () => cmd === "copytoken",
|
|
process: (callback) => {
|
|
utils.copyToClipboard(this.authToken)
|
|
callback(null, __('Token copied to clipboard: %s', this.authToken));
|
|
}
|
|
};
|
|
});
|
|
|
|
}
|
|
|
|
registerEvents() {
|
|
let self = this;
|
|
|
|
this.events.once('outputDone', () => {
|
|
const {port, host} = this.embark.config.webServerConfig;
|
|
this.logger.info(__('Access the web backend with the following url: %s',
|
|
(`http://${host}:${port}/embark?token=${this.authToken}`.underline)));
|
|
});
|
|
|
|
this.events.setCommandHandler('authenticator:authorize', (req, res, cb) => {
|
|
let authenticated = false;
|
|
if(!res.send) {
|
|
authenticated = (this.authToken === req.protocol);
|
|
} else {
|
|
let hash = self.generateRequestHash(req);
|
|
authenticated = (hash === req.headers['x-embark-request-hash']);
|
|
}
|
|
|
|
if(authenticated) return cb();
|
|
cb(ERROR_OBJ);
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = Authenticator;
|