From e76689da7f31dabc85ff11a3e85ecbe7d72df7f5 Mon Sep 17 00:00:00 2001 From: gilgameshskytrooper Date: Tue, 5 Oct 2021 19:11:09 -0500 Subject: [PATCH] Pass credentials using form post rather then url query parameters in backend examples to prevent credentials from getting leaked through browser cache https://owasp.org/www-community/vulnerabilities/Information_exposure_through_query_strings_in_url --- go-server-example/main.go | 6 +-- go-server-example/public/js/index.js | 61 +++++++++++++------------- node-server-example/public/js/index.js | 61 +++++++++++++------------- node-server-example/server.js | 17 +++---- php-server-example/js/index.js | 59 +++++++++++++------------ php-server-example/login/index.php | 4 +- 6 files changed, 104 insertions(+), 104 deletions(-) diff --git a/go-server-example/main.go b/go-server-example/main.go index 56c9f258..6dc52c96 100644 --- a/go-server-example/main.go +++ b/go-server-example/main.go @@ -55,11 +55,11 @@ func main() { r.Get("/favicon.ico", func(w http.ResponseWriter, req *http.Request) { w.Write(faviconBytes) }) - r.Get("/login", func(w http.ResponseWriter, req *http.Request) { + r.Post("/login", func(w http.ResponseWriter, req *http.Request) { ret := make(map[string]interface{}) - if req.URL.Query().Get("email") != DEMO_EMAIL { + if req.FormValue("email") != DEMO_EMAIL { ret["responseCode"] = "UNFD" ret["message"] = "User not found. Please make sure you entered the right userId and API credentials in config.go" marshaled, _ := json.Marshal(ret) @@ -67,7 +67,7 @@ func main() { return } - if req.URL.Query().Get("password") != DEMO_PASSWORD { + if req.FormValue("password") != DEMO_PASSWORD { ret["responseCode"] = "INPW" ret["message"] = "Incorrect Password" marshaled, _ := json.Marshal(ret) diff --git a/go-server-example/public/js/index.js b/go-server-example/public/js/index.js index 997d9d66..9207d382 100644 --- a/go-server-example/public/js/index.js +++ b/go-server-example/public/js/index.js @@ -52,17 +52,16 @@ function showForTime(elementSelector, timeInSeconds){ }, timeInSeconds + 200); } -function exampleLoginAPICall(values, callback) { - var bodyString = '?email=' + values.email + '&password=' + values.password; - var http = new XMLHttpRequest(); - http.open("GET", "/login" + bodyString, true); - http.send(null); - http.onreadystatechange = function() { - if (http.readyState === 4) { - var response = JSON.parse(http.responseText.trim()); - callback(response); - } - } +async function exampleLoginAPICall(values) { + let formData = new FormData() + formData.append('email', values.email); + formData.append('password', values.password); + + return await fetch('/login', {method: 'POST', body: formData}) + .then(response => response.json()) + .then((data) => { + return data; + }); } function isLivenessEnabled(){ @@ -291,7 +290,7 @@ window.onload = function(event) { return passedCheck; } - document.querySelector('#loginBtn').addEventListener('click', function() { + document.querySelector('#loginBtn').addEventListener('click', async function() { var em = document.querySelector('input[name="email"]').value; var pass = document.querySelector('input[name="password"]').value; var loginCreds = { @@ -301,26 +300,26 @@ window.onload = function(event) { if (validateCredentialsFormat(loginCreds)) { showLoader(true); - exampleLoginAPICall(loginCreds, function(response) { - if (response.responseCode === "SUCC" && response.token) { - window.loggedIn = true; - window.myVoiceIt.setSecureToken(response.token); - if(window.frontEndInitialized){ - showLoader(false); - showElement('#biometricOptions'); - } - hideElement('#loginBtn'); - hideElement('#formOverlay'); - showMessage('Please choose a 2FA verification option below'); - } else { - if(window.frontEndInitialized){ - showLoader(false); - } - // hideElement('#loginBtn'); - // hideElement('#formOverlay'); - showMessage(response.message, true); + const response = await exampleLoginAPICall(loginCreds); + + if (response.responseCode === "SUCC" && response.token) { + window.loggedIn = true; + window.myVoiceIt.setSecureToken(response.token); + if(window.frontEndInitialized){ + showLoader(false); + showElement('#biometricOptions'); } - }); + hideElement('#loginBtn'); + hideElement('#formOverlay'); + showMessage('Please choose a 2FA verification option below'); + } else { + if(window.frontEndInitialized){ + showLoader(false); + } + // hideElement('#loginBtn'); + // hideElement('#formOverlay'); + showMessage(response.message, true); + } } }); diff --git a/node-server-example/public/js/index.js b/node-server-example/public/js/index.js index 997d9d66..9207d382 100644 --- a/node-server-example/public/js/index.js +++ b/node-server-example/public/js/index.js @@ -52,17 +52,16 @@ function showForTime(elementSelector, timeInSeconds){ }, timeInSeconds + 200); } -function exampleLoginAPICall(values, callback) { - var bodyString = '?email=' + values.email + '&password=' + values.password; - var http = new XMLHttpRequest(); - http.open("GET", "/login" + bodyString, true); - http.send(null); - http.onreadystatechange = function() { - if (http.readyState === 4) { - var response = JSON.parse(http.responseText.trim()); - callback(response); - } - } +async function exampleLoginAPICall(values) { + let formData = new FormData() + formData.append('email', values.email); + formData.append('password', values.password); + + return await fetch('/login', {method: 'POST', body: formData}) + .then(response => response.json()) + .then((data) => { + return data; + }); } function isLivenessEnabled(){ @@ -291,7 +290,7 @@ window.onload = function(event) { return passedCheck; } - document.querySelector('#loginBtn').addEventListener('click', function() { + document.querySelector('#loginBtn').addEventListener('click', async function() { var em = document.querySelector('input[name="email"]').value; var pass = document.querySelector('input[name="password"]').value; var loginCreds = { @@ -301,26 +300,26 @@ window.onload = function(event) { if (validateCredentialsFormat(loginCreds)) { showLoader(true); - exampleLoginAPICall(loginCreds, function(response) { - if (response.responseCode === "SUCC" && response.token) { - window.loggedIn = true; - window.myVoiceIt.setSecureToken(response.token); - if(window.frontEndInitialized){ - showLoader(false); - showElement('#biometricOptions'); - } - hideElement('#loginBtn'); - hideElement('#formOverlay'); - showMessage('Please choose a 2FA verification option below'); - } else { - if(window.frontEndInitialized){ - showLoader(false); - } - // hideElement('#loginBtn'); - // hideElement('#formOverlay'); - showMessage(response.message, true); + const response = await exampleLoginAPICall(loginCreds); + + if (response.responseCode === "SUCC" && response.token) { + window.loggedIn = true; + window.myVoiceIt.setSecureToken(response.token); + if(window.frontEndInitialized){ + showLoader(false); + showElement('#biometricOptions'); } - }); + hideElement('#loginBtn'); + hideElement('#formOverlay'); + showMessage('Please choose a 2FA verification option below'); + } else { + if(window.frontEndInitialized){ + showLoader(false); + } + // hideElement('#loginBtn'); + // hideElement('#formOverlay'); + showMessage(response.message, true); + } } }); diff --git a/node-server-example/server.js b/node-server-example/server.js index ad6cc80b..2e8cbf90 100644 --- a/node-server-example/server.js +++ b/node-server-example/server.js @@ -4,7 +4,7 @@ const bodyParser = require('body-parser') const config = require('./config') const VoiceIt2WebSDK = require('../voiceit-node-websdk') // const = require('../voiceit-node-websdk/tokenGenerator') -const app = express() +const app = express(); const port = 3000 let test = ''; @@ -15,20 +15,21 @@ app.use(session({ secret: 'supersecretsessionkey', resave: false, saveUninitialized: true, -})) +})); app.use('/favicon.ico', express.static('public/images/favicon.ico')); // parse application/json -app.use(bodyParser.json()) +app.use(bodyParser.json()); // parse application/x-www-form-urlencoded -app.use(bodyParser.urlencoded({ extended: true })) +app.use(bodyParser.urlencoded({ extended: true })); // for parsing multipart/form-data const multer = require('multer')() +app.use(multer.array()); // serve all static files in public directory -app.use(express.static('public')) +app.use(express.static('public')); -app.get('/login', function (req, res) { - if(req.query.email === config.DEMO_EMAIL && req.query.password === config.DEMO_PASSWORD){ +app.post('/login', function (req, res) { + if(req.body.email === config.DEMO_EMAIL && req.body.password === config.DEMO_PASSWORD){ let generatedToken = ''; const userId = config.VOICEIT_TEST_USER_ID; if (userId.substring(0,4) === 'usr_'){ @@ -44,7 +45,7 @@ app.get('/login', function (req, res) { 'message' : 'Successfully authenticated user', 'token' : generatedToken }); - } else if (req.query.password !== config.DEMO_PASSWORD){ + } else if (req.body.password !== config.DEMO_PASSWORD){ res.json({ 'responseCode': 'INPW', 'message' : 'Incorrect Password' diff --git a/php-server-example/js/index.js b/php-server-example/js/index.js index b6495eec..d593ba4e 100644 --- a/php-server-example/js/index.js +++ b/php-server-example/js/index.js @@ -52,17 +52,16 @@ function showForTime(elementSelector, timeInSeconds){ }, timeInSeconds + 200); } -function exampleLoginAPICall(values, callback) { - var bodyString = '?email=' + values.email + '&password=' + values.password; - var http = new XMLHttpRequest(); - http.open("GET", "/login" + bodyString, true); - http.send(null); - http.onreadystatechange = function() { - if (http.readyState === 4) { - var response = JSON.parse(http.responseText.trim()); - callback(response); - } - } +async function exampleLoginAPICall(values) { + let formData = new FormData() + formData.append('email', values.email); + formData.append('password', values.password); + + return await fetch('/login', {method: 'POST', body: formData}) + .then(response => response.json()) + .then((data) => { + return data; + }); } function isLivenessEnabled(){ @@ -243,7 +242,7 @@ window.onload = function(event) { return passedCheck; } - document.querySelector('#loginBtn').addEventListener('click', function() { + document.querySelector('#loginBtn').addEventListener('click', async function() { var em = document.querySelector('input[name="email"]').value; var pass = document.querySelector('input[name="password"]').value; var loginCreds = { @@ -253,24 +252,26 @@ window.onload = function(event) { if (validateCredentialsFormat(loginCreds)) { showLoader(true); - exampleLoginAPICall(loginCreds, function(response) { - if (response.responseCode === "SUCC") { - window.loggedIn = true; - window.myVoiceIt.setSecureToken(response.token); - if(window.frontEndInitialized){ - showLoader(false); - showElement('#biometricOptions'); - } - hideElement('#loginBtn'); - hideElement('#formOverlay'); - showMessage('Please choose a 2FA verification option below'); - } else { - if(window.frontEndInitialized){ - showLoader(false); - } - showMessage(response.message, true); + const response = await exampleLoginAPICall(loginCreds); + + if (response.responseCode === "SUCC" && response.token) { + window.loggedIn = true; + window.myVoiceIt.setSecureToken(response.token); + if(window.frontEndInitialized){ + showLoader(false); + showElement('#biometricOptions'); } - }); + hideElement('#loginBtn'); + hideElement('#formOverlay'); + showMessage('Please choose a 2FA verification option below'); + } else { + if(window.frontEndInitialized){ + showLoader(false); + } + // hideElement('#loginBtn'); + // hideElement('#formOverlay'); + showMessage(response.message, true); + } } }); diff --git a/php-server-example/login/index.php b/php-server-example/login/index.php index 381165fe..8488c1c3 100644 --- a/php-server-example/login/index.php +++ b/php-server-example/login/index.php @@ -3,8 +3,8 @@ include('../config.php'); -$email = "".$_GET["email"]; -$password = "".$_GET["password"]; +$email = "".$_POST["email"]; +$password = "".$_POST["password"]; if($email == $DEMO_EMAIL && $password == $DEMO_PASSWORD){ header("HTTP/1.1 200 OK");