To logout a user, logged in using basic Auth, I am trying to follow advice on: link1 link2
I am using express-basic-auth to protect a few routes in my application.
An example of a protected route using it is as follows:
const basicAuth = require('express-basic-auth');
const protect = basicAuth({
users: { 'admin': 'secret' },
challenge: true
})
app.get('/protected', protect, function(req, res) {
console.log("authorization header ", req.headers.authorization);
console.log("user ", req.auth);
res.send('Success!');
});
With challenge: true in basicAuth we get a popup to enter username and password.
If the entered information is correct, we'll get Success! written on the screen.
The problem occurred when I wanted to logout the user. I researched and found that basic authentication is not built around logouts yet there were a few hacky ways of doing it.
To logout, we basically need to login with the wrong credentials. We can't ask a user to do that so I wanted to write a JavaScript snippet that would login with the wrong credentials and link that code to a logout button.
To logout I created a logout button and forced a logout using fetch with GET method and wrong credentials. The code is as follows:
const logoutLink = document.getElementById("logout");
logout.addEventListener("click", handleLogoutClick)
function handleLogoutClick() {
// Wrong credentials
let username = 'admin';
let password = 'passwd';
let url = `http://localhost:3000/protected`; // url cannot have credentials
let headers = new Headers();
headers.append('Content-Type', 'text/json');
headers.set('Authorization', 'Basic ' + btoa(username + ":" + password));
fetch(url, {method:'GET',
headers: headers})
.then(response => {
if (!response.ok) throw new Error(response.status);
return response.json();})
.then(data => {console.log("Data is", data)})
.catch(err => {console.log("Error is", err)})
The above code snippet worked in logging out a user on Chrome but did not work in Firefox.
In my browser, if I want to logout a user and I do: http://user:wrongPassword@localhost:3000/protected, then it logs out the user (works both for Chrome and Firefox)
However, I can't make a fetch request to http://user:wrongPassword@localhost:3000/protected URL so I have to make a request to http://localhost:3000/protected and passed the credentials as a header.
Also to test what might be wrong with the logout request, I tried making a login request using javascript. It seemed to work when I see the console.log statements in the browser as well as those I get on the terminal where the app is running (get a status 200). But when I try and access a protected route, I get the basicAuth pop-up to enter credentials again. (If I login manually in the browser, it doesn't ask for login credentials again)
The code for the login (which seems to work in terms of the 200 status request I get back) but is not actually working is as follows:
function userForm() {
const loginForm = document.getElementById('login-form');
loginForm.addEventListener("submit", handleFormSubmit)
function handleFormSubmit(e) {
e.preventDefault();
const formData = new FormData(document.querySelector('form'));
const formObject = {}
for (let pair of formData.entries()) {
formObject[pair[0]] = pair[1];
}
console.log(formObject);
const {username, password} = formObject;
const url = `http://localhost:3000/protected`;
let headers = new Headers();
headers.append('Content-Type', 'text/json');
headers.set('Authorization', 'Basic ' + btoa(username + ":" + password));
(async () => {
try {
const response = await fetch(url, {
method: 'GET',
headers: headers
});
console.log("response is", response);
if (response.status === 200) {
window.location.href = url;
}
} catch (error) {
console.log("An error occured in form submission");
}
})(url, headers);
}
}
userForm();
We get a response.status of 200 but when the browser gets redirected to the protected route, I get a pop-up to enter credentials. When I make a fetch call to a protected route, using vanilla JS, I can see the authorization headers and user value printed to terminal (from the console.log statements in app.get('/protected', protect, function(req, res) {}
I know that basicAuth is not something to be used in production. But I would like to know why doing a login like this is not working. And also why logout is not working for firefox but working for chrome. Also are there some resources I can consult which might clear basicAuth for me. The package exxpress-basic-auth is not very clear in this regard.
Closing the browser or refreshing the browser does logout the user. But if I could write a script for a logout button, and maybe also for login, it would be much better.