1

Really simple question but I couldn't find anything anywhere about this.

I'm trying to make a fetch request with the original authentication header. My app is using http basic authentication for all routes which works fine. with my clientside js I'm trying to create a request to /api/thing which requires the same http basic credentials as the original page request.

How do I pass those original credentials aloing withthe request?

fetch("http://localhost:33507/api/thing")
.then(function(response) {
    return response.text()
})
.then(function(responseText) {
    console.log(responseText);
});

edit: I know I can pass headers like so:

fetch("http://localhost:33507/ssh", {headers: {"Authorization": "basic u:p"}})

But that's not the issue, the issue is getting the username and password. I can't really ask the user to fill them in on every request. Surely there is a way to pass them along without looking at them?

edit2: my flow is like this:

1 user requests page - server asks for http basic credentials.

2 user sends credentials - server replies with page.

3 user presses button to send fetch request - server replies with resource.

The problem here is that I can't find a way to pass those credentials when doing the fetch request

SnelleJelle
  • 933
  • 5
  • 18
  • 35
  • use the second argument to `fetch` - see [documentation](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Supplying_request_options) – Jaromanda X Jan 08 '18 at 22:48
  • yeah I know but, I can't acces the original header because permissions – SnelleJelle Jan 08 '18 at 22:49
  • oh, because it's cross origin? by `the original header` do you mean response header? that's where [Access-Control-Expose-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers) on the server may help? – Jaromanda X Jan 08 '18 at 22:50
  • So in the page response I expose the Authorization header, and in my fetch I get the value and pass it along ? – SnelleJelle Jan 08 '18 at 22:52
  • Did you try: http://username:password@example.com/ url format ? – Peter Jan 08 '18 at 22:53
  • huh? Isn't `Authorization` a request header? If you've sent it once (i.e. you say "original authentication header") then what's stopping you from accessing it later? You created that header, didn't you? – Jaromanda X Jan 08 '18 at 22:53
  • my bad, got some thing mixed up (it's almost midnight here). I can't find a code sample to access the Authorization header, can you provide one? – SnelleJelle Jan 08 '18 at 22:58
  • @JaromandaX I edited my post to better describe the flow I'm trying to achieve. – SnelleJelle Jan 08 '18 at 23:01
  • @Peter I didn't try username:password@example.com . But I would still have to fill in the username and password which I can't access. – SnelleJelle Jan 08 '18 at 23:04
  • oh, right, the dialogue that asks for username/password - see where you say `server replies with page` - perhaps some sort of authentication token / session id or some such should be returned in that page for subsequent pages to use - you'd need to implement this on your server side, which you haven't described at all :p – Jaromanda X Jan 08 '18 at 23:04
  • @JaromandaX oh so I'm not supposed to pass the authorization header along in my code in the first place ? – SnelleJelle Jan 08 '18 at 23:05
  • @SnelleJelle, I believe your problem is how to save the user session in your browser. Typically, not all requests to the server are made with the Auth header so that the server doesn't need to keep checking that the credentials are correct in all the requests. You should probably see how to maintain the user's session in the browser which you can then access on the server. – Hawkes Jan 08 '18 at 23:06
  • Not sure what you mean to be honest - of course the initial login will pass the authorization header in the request – Jaromanda X Jan 08 '18 at 23:06
  • @JaromandaX, you're absolutely correct. But as I understand the question, the initial login is not the issue here, trying to fetch protected resources after the login has happened needs a different approach which would be session handling IMO. – Hawkes Jan 08 '18 at 23:08
  • Basic auth is handled by the browser, these days it is not popular because of the issue you have (and it is unsecure etc...) Most sites are using login form with username and password, and send a session token back to the user (typicaly using cookies) thats call Authentication. Later when the user makes another request they check this token, and check the user has access to the resource or not. Thats called Authorization. Idk your backend, but there are lots of tutorial how to implement it in different programming languages. – Peter Jan 08 '18 at 23:12

2 Answers2

2

I suppose that you should be able to do it without adding your credentials explicitly in the JavaScript code. Adding credentials: 'include' to you fetch request options object should be enough if your client is already authenticated in the same domain:

let url = "some url";
let options = { "credentials": "include" };
fetch(url, options).then( ... ).catch( ... );
1

I believe what you are looking for is a way to not have to set the headers every time.

(I'm going to assume you are programming for the browser)

One options is to is to store the username and password in local storage and just wrap the fetch in your own method.

/**
 * Called after user enters credentials, saves to credentials
 * to localStorage for use in subsequent calls.
 * @param {string} userName
 * @param {string} password
 */
saveCredentials(userName, password) {
  localStorage.setItem('credentials', 'basic '+userName+':'+password);
}


/**
 * Site wide custom fetch wrapper. Appends default headers, calls the
 * standard fetch method, and returns a fetch promise.
 * @param {string} url
 * @param {object} options
 * @returns {Promise}
 */
myFetch(url, options) {
  var options = options || {};
  var options.headers = options.headers || {};
  options.headers['Authorization'] = localStorage.getItem('credentials');
  return fetch(url, options);
}

Another options is to use something like this:

https://github.com/moll/js-fetch-defaults

This allows you to set default headers for fetch once, then all subsequent fetches will use the same ones.

Arthur Goldsmith
  • 2,976
  • 2
  • 17
  • 7
  • Storing user credentials on the front-end is a really bad idea because your user accounts may be compromised via XSS. – Alex Oct 14 '20 at 01:09