diff options
Diffstat (limited to 'src/routers/vault')
-rw-r--r-- | src/routers/vault/middlewares/identity.js | 4 | ||||
-rw-r--r-- | src/routers/vault/middlewares/session.js | 7 | ||||
-rw-r--r-- | src/routers/vault/types/Session.js | 25 | ||||
-rw-r--r-- | src/routers/vault/utils/validate.js | 9 |
4 files changed, 32 insertions, 13 deletions
diff --git a/src/routers/vault/middlewares/identity.js b/src/routers/vault/middlewares/identity.js index 14903c3..6e8be7f 100644 --- a/src/routers/vault/middlewares/identity.js +++ b/src/routers/vault/middlewares/identity.js @@ -1,9 +1,9 @@ "use strict"; -const uuidv4 = require("uuid/v4"); const nodemailer = require("nodemailer"); const Claim = require("../utils/claim.js"); const validate = require("../utils/validate.js"); const Identity = require("../types/Identity.js"); +const Session = require("../types/Session.js"); let transporter = nodemailer.createTransport({ sendmail: true, @@ -181,7 +181,7 @@ const add_identity = async (req, res, next) => { let uuid; do { // avoid collisions - uuid = uuidv4(); + uuid = await Session.generateToken(); } while (req.app.locals.session.get(uuid)); req.app.locals.identity_pending.set(uuid, { diff --git a/src/routers/vault/middlewares/session.js b/src/routers/vault/middlewares/session.js index 1c322e4..71db21c 100644 --- a/src/routers/vault/middlewares/session.js +++ b/src/routers/vault/middlewares/session.js @@ -1,5 +1,4 @@ "use strict"; -const uuidv4 = require("uuid/v4"); const nodemailer = require("nodemailer"); const Claim = require("../utils/claim.js"); const Session = require("../types/Session.js"); @@ -221,7 +220,7 @@ const auth_session = async (req, res) => { } // immediately change the session uuid - const new_uuid = uuidv4(); + const new_uuid = await Session.generateToken(); req.app.locals.session.set(new_uuid, session); req.app.locals.session.delete(token); // revoke the old uuid @@ -253,7 +252,7 @@ const new_session = async (req, res, next) => { // account creation request let uuid; do { // avoid collisions - uuid = uuidv4(); + uuid = await Session.generateToken(); } while (req.app.locals.session.get(uuid)); const session = new Session(req.ip, email); @@ -344,7 +343,7 @@ const new_session = async (req, res, next) => { let uuid; do { // avoid collisions - uuid = uuidv4(); + uuid = await Session.generateToken(); } while (req.app.locals.session.get(uuid)); const session = new Session(req.ip, email); diff --git a/src/routers/vault/types/Session.js b/src/routers/vault/types/Session.js index 59737b3..d1b3943 100644 --- a/src/routers/vault/types/Session.js +++ b/src/routers/vault/types/Session.js @@ -1,8 +1,15 @@ -const uuidv4 = require("uuid/v4"); +const nanoid = require("nanoid"); +const dictionaries = require("nanoid-dictionary"); const Identity = require("./Identity.js"); const EvolAccount = require("./EvolAccount.js"); const LegacyAccount = require("./LegacyAccount.js"); +/** custom nanoid generators */ +const newToken = { + n23: nanoid.customAlphabet(dictionaries.nolookalikes, 23), + n36: () => nanoid.nanoid(36), +}; + /** * holds a cache of all the user data fetched from SQL */ @@ -72,18 +79,26 @@ module.exports = class Session { constructor (ip, email) { this.ip = ip; this.email = email.toLowerCase(); - this.secret = uuidv4(); + this.secret = newToken.n36(); + } + + /** + * generate a secure unique token that is shared with the end-user. + * excludes lookalike characters but is still stronger than uuidv4 + * @param {number} - the token length + */ + static async generateToken () { + return newToken.n23(); } /** * serialize for sending over the network - * @param {*} key */ - toJSON (key) { + toJSON () { return { expires: this.expires, identity: this.identity.id, - } + }; } /** diff --git a/src/routers/vault/utils/validate.js b/src/routers/vault/utils/validate.js index 5f2f2a6..3432d30 100644 --- a/src/routers/vault/utils/validate.js +++ b/src/routers/vault/utils/validate.js @@ -1,5 +1,6 @@ "use strict"; const Session = require("../types/Session.js"); +const nolookalikes = require("nanoid-dictionary/nolookalikes"); /** thrown when the user attempts to bypass security measures */ class BypassAttempt extends Error {}; @@ -10,6 +11,10 @@ class ValidationError extends Error {}; const regexes = { /** a Universally Unique Identifier */ uuid: /^[0-9a-f]{8}(?:\-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i, + /** nolookalikes nanoid */ + nano23: new RegExp(`^[${nolookalikes}]{23}$`), + /** nanoid */ + nano36: /^[A-Za-z0-9_-]{36}$/, /** tmwa password */ any23: /^[^\s][^\t\r\n]{2,21}[^\s]$/, /** hercules password */ @@ -79,7 +84,7 @@ const get_prop = (req, prop, regex = null) => { const get_secret = (req, res) => { const token = req.get("X-VAULT-TOKEN") || ""; - if (!token.match(regexes.uuid)) { + if (!token.match(regexes.nano36)) { res.status(400).json({ status: "error", error: "missing secret key", @@ -101,7 +106,7 @@ const get_secret = (req, res) => { const get_raw_session = (req, res) => { const token = String(req.get("X-VAULT-SESSION") || ""); - if (!token.match(regexes.uuid)) { + if (!token.match(regexes.nano23)) { res.status(400).json({ status: "error", error: "missing session key", |