summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgumi <git@gumi.ca>2020-03-31 14:36:40 -0400
committergumi <git@gumi.ca>2020-03-31 14:36:40 -0400
commit4d6545e66feb0e7ec53c76a3bf0247c1c3629dd4 (patch)
tree51bac6e432726a472fc5b7163f6f35c2823a565f /src
parent930485dfe22db16f5b613750eb9518bb64b4fe4f (diff)
downloadapi-4d6545e66feb0e7ec53c76a3bf0247c1c3629dd4.tar.gz
api-4d6545e66feb0e7ec53c76a3bf0247c1c3629dd4.tar.bz2
api-4d6545e66feb0e7ec53c76a3bf0247c1c3629dd4.tar.xz
api-4d6545e66feb0e7ec53c76a3bf0247c1c3629dd4.zip
add support for nanoid for session tokens
Diffstat (limited to 'src')
-rw-r--r--src/routers/vault/middlewares/identity.js4
-rw-r--r--src/routers/vault/middlewares/session.js7
-rw-r--r--src/routers/vault/types/Session.js25
-rw-r--r--src/routers/vault/utils/validate.js9
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",