1

Background:

Hello everyone, I'm working on an AJAX login function for a website and I'm trying to use the Argon2 KDF (library) to derive a (somewhat) resource-intensive secret in the browser itself from a user-provided password before it is sent to the server for verification. The site utilizes TLS so I think from a security standpoint this is kind of a moot point, but I'd rather the client do this part of the work rather than the server, and this is more of a learning experience than a production site anyway.

Question:

The example code correctly computes the hash within my project, verifiable by the output from console.log(h.hashHex), but I've tried dozens of ways to try to assign the value to a variable to use later in the same function. I realize a Promise is asynchronous so I'm sure I'm going wrong somewhere regarding threads. When debugging, the variable that should be a hex string is either still undefined or optimized away. I'm sure there's some simple thing I'm missing but looking at similar questions (1, 2, 3) I still can't get it to work and don't have too much experience in JavaScript. Thanks for your input!

Sample Code (Works)

argon2.hash({ pass: $("#password").val(), salt: 'somesalt' })
.then(h => console.log(h.hash, h.hashHex, h.encoded))
.catch(e => console.error(e.message, e.code));

Modification 1 (Doesn't work):

function do_login() {
  ...
  var password;
  argon2.hash({ pass: $("#password").val(), salt: 'somesalt' })
  .then(h => {password=h.hashHex})
  .catch(e => console.error(e.message, e.code));
  ...
}

Modification 2 (Also doesn't work):

function submitLogin(email, pass) {
  ...
  $.ajax
  ({
    type:'post',
    url:'/login',
    data:{
      do_login:"do_login",
      email:email,
      password:pass
    },
    success:function(response) {
      ...
    }
  });
}

function do_login()
{
  var email=$("#username").val();
  var password = $("#password").val();
  argon2.hash({ pass: password, salt: 'somesalt' })
  .then(h=> function(h){submitLogin(email,h.hashHex);return false;})
  .catch(e => function(e){console.error(e.message, e.code);return false;});
}

Update (answer below)

function submitLogin(email, pass) {
  ...
  $.ajax
  ({
    type:'post',
    url:'/login',
    data:{
      do_login:"do_login",
      email:email,
      password:pass
    },
    success:function(response) {
    ...
    }
  });
}

function do_login()
{
  var email=$("#username").val();
  var password = $("#password").val();
  argon2.hash({ pass: password, salt: 'somesalt' })
  .then(h=>submitLogin(email,h.hashHex))
  .catch(e => console.error(e.message, e.code));
  return false;
}
Jim
  • 587
  • 2
  • 6
  • 19

1 Answers1

2

Modification 1 won't work, because password will be set asynchronously, later, after do_login has returned.

Modification 2 doesn't work due to a typo; you have

.then(h=> function(h){submitLogin(email,h.hashHex);return false;})

but this uses both an arrow function h => and a function (h), twice as many functions as you actually want. This should work better:

.then(h => { submitLogin(email, h.hashHex); })

(In the next line, the catch handler has the same bug, though, so change both.)

Jason Orendorff
  • 42,793
  • 6
  • 62
  • 96
  • got it, thanks! I had the correct argon2.hash() line earlier on when I was fiddling around but that was before I broke it into two functions and started changing stuff. I'll update my question with the answer. – Jim Jan 24 '19 at 00:43