2

I'm trying to create a simple login form using Node/Express/Passport/Javascript with Basic authentication, but can't get it to work. What I want is to have a page where you input your credentials and hit "login". If these credentials are correct, then the user should be redirected to a page that is protected by basic auth, without asking for my credentials again. This seems like it should be really simple to do, but I keep running into problems.

Currently, I have a page where you input your login credentials (username and password). Hitting login makes an axios POST request to a /login endpoint where it verifies the login credentials. This endpoint returns status code 200 if the credentials are correct. If the response is 200 Success, I redirect the user to the basic-auth protected page. The server is using passport express middleware to serialises the user and maintain a user session. But this information seems to be lost on redirect and I can't find a way to set the basic auth headers on the redirect. Hence, the protected page I redirected to asks me for my credentials again. I've tried to fix it by sending the basic auth credentials again:

window.location.replace(http://username:password@website/directory/blahblah)

but most modern browsers seem to strip out basic auth credentials, so that doesn't work.

I was able to get it to work by putting the username and password in the url:

window.location.replace(http://website/directory/blahblah?username=uname&password=password)

but that seems like a terrible and insecure way of solving what should have a simple solution, since this method means that the username and password will end up appearing in my browser history. Is there a better way to implement such a login form?

The server code is a standard express server that uses passport.authenticate middleware with sessions enabled. What I find weird is that when my POST request returns, the req.session.passport.user contains the serialised user, so the code seems to be working properly, so I suspect that there is an issue with my HTML code. My current HTML login form is as follows:

<!DOCTYPE html>
<html>
  <head>
    <title>Login</title>
  </head>
  <body>
    <form method="get" action="javascript:loginFn()">
      <input name="username" type="text" value="uname" >
      <input name="password" type="password" value="pword">
      <input type="submit">
    </form>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script>
      const endpoint = 'login';
      const nextEndpoint = 'authorize';
      //function redirect(url, method) {
      //  var form = document.createElement('form');
      //  form.method = method;
      //  form.action = url;
      //  document.body.appendChild(form);
      //  form.submit();
      //};

      async function loginFn(){


        const username = document.querySelector('form [name=username]');
        const password = document.querySelector('form [name=password]');

        const uriParts = location.href.split('://');
        const http = uriParts[0];
        uriParts.splice(0, 1);
        var targetUri = `${http}://${username.value}:${password.value}@${uriParts.join('://').replace(endpoint, nextEndpoint)}`;

        // If credentials valid, the response code will be 200 Success
        const res = await axios
        .request({
          baseURL: targetUri,
          // Username and password used for basic auth
          method: 'POST',
          auth: {
            username: username.value,
            password: password.value,
          },
          params: {
            login_only: true,
          },
        })
        .catch((err) => {
          // Unable to connect to the server, redirect to the NoConnection page.
          if (err.message === 'Network Error') {
            throw new Error('Unstable database connection');
          }
          if(err.request.status === 404){
            throw new Error('Invalid callback URL');
          }
          if (err.request.status === 401) {
            // Incorrect login credentials
            throw new Error('Invalid login credentials');
          }
        });
        if(res.status === 200){
          // How do I NOT put the username and password in the URL redirect
          window.location.replace(targetUri + '?username=uname&password=pword');
        }
      }
    </script>
  </body>
</html>
keithlee96
  • 1,154
  • 1
  • 9
  • 16
  • this could be helpful: https://stackoverflow.com/questions/40755622/how-to-use-session-variable-with-nodejs - use session variables basically – enhzflep May 03 '18 at 02:02
  • @enhzflep I don't think that works, since the req.session seems to be empty on the redirect API call. – keithlee96 May 03 '18 at 02:51
  • User query string to authenticate is not recommended. Anyway, I think this issue maybe caused by the **cookie** didn't save in the browser. So have you checked if there is any cookie appear after **AJAX** request? – Kevin Law May 03 '18 at 02:56
  • @KevinLaw Is there a way to save save the cookie from an Axios request? – keithlee96 May 03 '18 at 02:57
  • https://stackoverflow.com/questions/46288437/set-cookie-header-has-no-effect/46412839#46412839 – Kevin Law May 03 '18 at 03:10
  • @KevinLaw I know how to set the cookie. I don't know how to get the cookie from the axios response object. I've tried withCredentials: true, but that didn't work. – keithlee96 May 03 '18 at 03:14
  • You are not required to set cookie by your self. What you need to do is check if there is a **set-cookie** header alone with axios response. if it existed, cookie will be stored into browser automatically. – Kevin Law May 03 '18 at 03:29
  • @KevinLaw How do I check if there is a set-cookie header? – keithlee96 May 03 '18 at 03:43
  • Open Chrome developer tool, switch to network tab. Select a request record, check response headers. – Kevin Law May 03 '18 at 04:46
  • Hmm, I don't see a set-cookie header. Is that the problem? If so, how do I fix it? – keithlee96 May 03 '18 at 05:44
  • @KevinLaw set-cookie header is not listed. Is that the problem? – keithlee96 May 03 '18 at 07:17
  • Yes, if there is no set-cookie header, session wouldn't work as server side could not know your session id. In other words, the issue came from server side. – Kevin Law May 03 '18 at 07:19

0 Answers0