1

I get a plain API written in node.js such as this one:

const express = require('express')
const app = express();

app.post('/api/data', (req, res) => {
  res.status(200).json({
    data: [1,2,3,3,1,3,5,2,3,4,4,7]
  })
})

app.use('/gui', express.static('./gui'))

app.listen(8080, () => { console.log("OK") })

and a client javascript code accessing it with the fetch function, this way (e.g. ./gui/index.html):

fetch('/api/data', {
  method: 'post',
  headers: {
    'Accept': 'application/json', 'Content-Type': 'application/json'
  },
  body: JSON.stringify(json)
})
.then( res => { console.log(res })

It works fine, but now I want to put this API behind basic auth without changing the API code using nginx as man in the middle. The config file looks like:

server {
  listen 80;

  location / {
    auth_basic "Private Area";
    auth_basic_user_file .htpasswd; 

    proxy_pass http://localhost:8080;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
  }
}

Now, when I open the page in the browser, it asks for the auth infos, displays the HTML, but the AJAX accesses fail with a 401 error.

After checking it looks like the browser does not send the Authorization headers for the AJAX accesses.

The question is: is there a way to make the basic auth transparent to my API and GUI? I am doing something wrong?

Edit

It has been suggested that this question is a duplicate of Basic authentication with fetch?

I know how to set the headers explicitly to fetch. What I want here is the browser to set them implicitly when the application is behind basic auth, without any modification to my client code.

4
  • Possible duplicate of Basic authentication with fetch? Commented Jun 19, 2018 at 5:56
  • 1
    Please read on developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch about the usage of the credentials option, it might already be what you need. Commented Jun 19, 2018 at 6:19
  • @Tomalak: thank you! Looks like the answer was RTFM. I had to specify credentials: 'include' in the options of the fetch. I can accept your answer if you write one. Commented Jun 19, 2018 at 7:22
  • 1
    I wasn't sure if that would include basic auth headers, so I hesitated. It's fine if you write the answer, I'll upvote and everybody is happy. :) Commented Jun 19, 2018 at 7:23

1 Answer 1

1

As kindly suggested by @Tomalak, and according to https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

By default, fetch won't send or receive any cookies from the server, resulting in unauthenticated requests if the site relies on maintaining a user session (to send cookies, the credentials init option must be set).

In other words, all I had to do is to modify my call to fetch this way:

fetch('/api/data', {
  credentials: 'include',
  method: 'post',
  headers: {
    'Accept': 'application/json', 'Content-Type': 'application/json'
  },
  body: JSON.stringify(json)
})
.then( res => { console.log(res) })

Note the credentials: 'include' in fetch options (it is possible to use same-origin instead of include for tighter security).

This way, the browser will implicitly set the auth headers if necessary.

Sign up to request clarification or add additional context in comments.

2 Comments

Can you try credentials: 'same-origin' and confirm whether this works as well?
From what I read about the difference between same-origin and include, I think so, too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.