From b0a5b5d2927535d2acb99f69d871c6c510b3ffe6 Mon Sep 17 00:00:00 2001 From: Allen Pigar Date: Wed, 16 Nov 2022 19:41:54 +0800 Subject: [PATCH 1/2] Added Two Factor Authentication (2FA) --- src/services/auth/auth.js | 41 ++++++++++++++++++++++++++ src/services/auth/auth.test.js | 53 +++++++++++++++++++++++++++------- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/src/services/auth/auth.js b/src/services/auth/auth.js index 037e443..cb87363 100644 --- a/src/services/auth/auth.js +++ b/src/services/auth/auth.js @@ -68,4 +68,45 @@ module.exports = class Auth { throw err; }); } + + async verify2Fa(token, mfatoken) { + if (!token) { + return { + status: 400, + message: "Auth:verify2Fa() called without `token` argument", + verified: false, + }; + } + + if (!mfatoken) { + return { + status: 400, + message: "Auth:verify2Fa() called without `mfatoken` argument", + verified: false, + }; + } + + const form = new FormData(); + form.append("token", mfatoken); + + return fetch(`${this.authURL}/verify-2fa`, { + method: "POST", + body: form, + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + return res.json().then((data) => { + return { + ...data, + verified: data.code === 200 ? true : false, + }; + }); + }) + .catch((err) => { + console.log("verify2Fa: catch: ", err); + throw err; + }); + } }; diff --git a/src/services/auth/auth.test.js b/src/services/auth/auth.test.js index c7481e4..abd6af2 100644 --- a/src/services/auth/auth.test.js +++ b/src/services/auth/auth.test.js @@ -5,17 +5,17 @@ require("dotenv").config(); const test = require("ava"); const Auth = require("./auth"); const auth = new Auth({ - authURL: process.env.ZESTY_AUTH_API + authURL: process.env.ZESTY_AUTH_API, }); const badAuth = new Auth({ - authURL: "http://localhost:9999" + authURL: "http://localhost:9999", }); // NOTE: We explicitly do not catch promise rejections, // instead we let them throw failing the test. Ava will // print the uncaught error to the console -test("login:200", async t => { +test("login:200", async (t) => { const res = await auth.login( process.env.ZESTY_USER_EMAIL, process.env.ZESTY_USER_PASSWORD @@ -25,7 +25,7 @@ test("login:200", async t => { t.not("", res.token); }); -test("verifyToken:200", async t => { +test("verifyToken:200", async (t) => { const session = await auth.login( process.env.ZESTY_USER_EMAIL, process.env.ZESTY_USER_PASSWORD @@ -36,11 +36,44 @@ test("verifyToken:200", async t => { t.is(res.verified, true); }); +test("verify2Fa:200", async (t) => { + const session = await auth.login( + process.env.ZESTY_USER_EMAIL, + process.env.ZESTY_USER_PASSWORD + ); + + //add your otp token + var mfatoken = "0000000000"; + const res = await auth.verify2Fa(session.token, mfatoken); + t.is(res.code, 200); + t.is(res.verified, true); +}); + /** * Causes account lock breaking tests */ -test.skip("login:400", async t => { +test("verify2Fa:400", async (t) => { + const missingToken = await auth.verify2Fa(null, null); + t.is(missingToken.status, 400); + t.is( + missingToken.message, + "Auth:verify2Fa() called without `token` argument" + ); + + const session = await auth.login( + process.env.ZESTY_USER_EMAIL, + process.env.ZESTY_USER_PASSWORD + ); + const missingMfaToken = await auth.verify2Fa(session.token, null); + t.is(missingMfaToken.status, 400); + t.is( + missingMfaToken.message, + "Auth:verify2Fa() called without `mfatoken` argument" + ); +}); + +test.skip("login:400", async (t) => { const missingEmail = await auth.login(null, null); t.is(missingEmail.statusCode, 400); t.is(missingEmail.message, "Auth:login() missing required argument `email`"); @@ -53,7 +86,7 @@ test.skip("login:400", async t => { ); }); -test.skip("login:401||403", async t => { +test.skip("login:401||403", async (t) => { const res = await auth.login("BAD@USERNAME", "BAD PASSWORD"); // After 5 failed login attempts the auth service locks the account and returns @@ -62,7 +95,7 @@ test.skip("login:401||403", async t => { t.truthy(res.statusCode == 401 || res.statusCode == 403); }); -test.skip("login:error", async t => { +test.skip("login:error", async (t) => { try { const res = await badAuth.login( process.env.ZESTY_USER_EMAIL, @@ -74,19 +107,19 @@ test.skip("login:error", async t => { } }); -test.skip("verifyToken:401", async t => { +test.skip("verifyToken:401", async (t) => { const res = await auth.verifyToken("BADTOKEN"); t.is(res.statusCode, 401); t.is(res.verified, false); }); -test.skip("verifyToken:missing token", async t => { +test.skip("verifyToken:missing token", async (t) => { const res = await auth.verifyToken(); t.is(res.verified, false); }); -test.skip("verifyToken:error", async t => { +test.skip("verifyToken:error", async (t) => { try { const res = await badAuth.verifyToken("BADTOKEN"); t.fail(); From ff67a6104a8a8ab724951bdfe44ec1e5eb65a7e2 Mon Sep 17 00:00:00 2001 From: Allen Pigar Date: Wed, 16 Nov 2022 21:04:07 +0800 Subject: [PATCH 2/2] added auto verify 2fa --- src/services/auth/auth.js | 32 ++++++++++++++++++++++++++++++-- src/services/auth/auth.test.js | 24 +++++++++++++++++++++--- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/services/auth/auth.js b/src/services/auth/auth.js index cb87363..f964095 100644 --- a/src/services/auth/auth.js +++ b/src/services/auth/auth.js @@ -69,10 +69,38 @@ module.exports = class Auth { }); } + async verify2FaAuto(token) { + if (!token) { + return { + code: 400, + message: "Auth:verify2FaAuto() called without `token` argument", + verified: false, + }; + } + return fetch(`${this.authURL}/verify-2fa`, { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + return res.json().then((data) => { + return { + ...data, + verified: data.code === 200 ? true : false, + }; + }); + }) + .catch((err) => { + console.log("verify2FaAuto: catch: ", err); + throw err; + }); + } + async verify2Fa(token, mfatoken) { if (!token) { return { - status: 400, + code: 400, message: "Auth:verify2Fa() called without `token` argument", verified: false, }; @@ -80,7 +108,7 @@ module.exports = class Auth { if (!mfatoken) { return { - status: 400, + code: 400, message: "Auth:verify2Fa() called without `mfatoken` argument", verified: false, }; diff --git a/src/services/auth/auth.test.js b/src/services/auth/auth.test.js index abd6af2..b09dfa1 100644 --- a/src/services/auth/auth.test.js +++ b/src/services/auth/auth.test.js @@ -36,6 +36,24 @@ test("verifyToken:200", async (t) => { t.is(res.verified, true); }); +test.skip("verify2FaAuto:200", async (t) => { + const session = await auth.login( + process.env.ZESTY_USER_EMAIL, + process.env.ZESTY_USER_PASSWORD + ); + + var done = false; + console.log("Confirm Authy within 10 secs."); + do { + const res = await auth.verify2FaAuto(session.token); + if (res.status === "OK") { + t.is(res.code, 200); + t.is(res.verified, true); + done = true; + } + } while (!done); +}); + test("verify2Fa:200", async (t) => { const session = await auth.login( process.env.ZESTY_USER_EMAIL, @@ -43,7 +61,7 @@ test("verify2Fa:200", async (t) => { ); //add your otp token - var mfatoken = "0000000000"; + var mfatoken = "1699168"; const res = await auth.verify2Fa(session.token, mfatoken); t.is(res.code, 200); t.is(res.verified, true); @@ -55,7 +73,7 @@ test("verify2Fa:200", async (t) => { test("verify2Fa:400", async (t) => { const missingToken = await auth.verify2Fa(null, null); - t.is(missingToken.status, 400); + t.is(missingToken.code, 400); t.is( missingToken.message, "Auth:verify2Fa() called without `token` argument" @@ -66,7 +84,7 @@ test("verify2Fa:400", async (t) => { process.env.ZESTY_USER_PASSWORD ); const missingMfaToken = await auth.verify2Fa(session.token, null); - t.is(missingMfaToken.status, 400); + t.is(missingMfaToken.code, 400); t.is( missingMfaToken.message, "Auth:verify2Fa() called without `mfatoken` argument"