javascriptxmlhttprequestsuperagentpassword-manager

Prevent password manager from asking to save password on xhr request


We are sending requests to an external API. It is an public API but still requires to sent basic auth authentication. Since it is a public user with no further access this is no security issue. But when those requests are executed the password manager keeps asking to save the basic auth data for this external url. This is annoying and the users on the website might get confused why they suddenly can save a username and password for a domain they do not know.

I would like to know if we can somehow make password managers in general ignore those requests.

So far we only noticed last pass with this behavior (bitwarden and chrome build in do not show this behavior). I am wondering if it is a problem specifically with the last pass extension or if it might be happening with other managers too.

My research so far did not show any results.

It can be reproduced in this fiddle with the an request like this:

(function() {
  superagent('GET', 'https://httpbin.org/anything')
    .auth('Username', 'Password')
    .type('application/json')
    .then(res => {
      console.debug('res', res);
    })
    .catch(err => {
      console.debug('err', err)
    });
})();

This is how last pass asks to save the credentials:
last pass example

As per comment suggested I tried to implement the url as username:password@example.com and LastPass does not recognize this anymore.

I verified via curl that the API works with this syntax but when I implemented it into like this:

(function() {
  superagent('GET', 'https://username:password@httpbin.org/anything')
    .auth('Username', 'Password')
    .type('application/json')
    .then(res => {
      console.debug('res', res);
    })
    .catch(err => {
      console.debug('err', err)
    });
})();

the API does not accept this anymore.

I contacted the developer of the API and he said the request did not contain the authentication information. I wonder if the browser somehow stripped it out? When accessing the URL directly in the browser it works, but is the browser converting it behind the scenes into a header?
Calling the URL in Firefox shows an authentication header but in chrome it does not. Either way both seem to work.


Solution

  • We have now come up with a solution for this issue. We are using a proxy to set the authentication header and pass the request along to the api.

    I remove the authentication from the original code and changed the url to the proxy path:

    (function() {
      superagent('GET', 'https://example.com/proxy-path')
        .type('application/json')
        .then(res => {
          console.debug('res', res);
        })
        .catch(err => {
          console.debug('err', err)
        });
    })();
    

    Then in the apache we configured the proxy to add the header if it is not set:

    SSLProxyEngine on
    ProxyPass /proxy-path https://api-url.com/
    ProxyPassReverse /proxy-path https://api-url.com/
    <LocationMatch "/proxy-path">
        RequestHeader setifempty authorization "Basic base64Credentials"
    </LocationMatch>
    

    With this solution LastPass has no authentication header to scan and the request ist passed through to the api with the authentication header in place.

    The disadvantage of the proxy is that we have an increased response time of 20-30ms. In our case this is not much and bearable .