Reputation: 1273
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.
Upvotes: 1
Views: 387
Reputation: 1273
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.
Upvotes: 1