I've tried to understand and implement the Basic Authentication algorithm, and looks like it works as expected. Now I have a problem: the Authorization
header in the request never expires (at least, it hasn't for a couple of days now), so the client always sees the protected content, whereas I want them to re-authenticate every minute.
Judging by this answer, the problem is that this is basically how browsers work, – they remember user credentials for convenience. Alas, the answer does not provide any solution, only an explanation, and I would really love to not rely on client browser settings.
What can I add on the server so that the Authorization
header in the request, once created, expires after 1 minute, and isn't included in the requests sent 1 minute later?
I'm using express
lib for the server and express-session
for cookies (see the code of actual authentication middleware below). The cookies are set to have Max-Age
of 60 seconds:
app.use(session({
secret: process.env.EXPRESS_SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
maxAge: 60_000,
},
}));
The GET /private
request needs to have the correct Authorization
header to reach to the content. The problem with the approach below is that while req.session.authenticated
is undefined
after 1 minute (cookie session expired), the req.get("Authorization")
is still present (neither null
, nor undefined
), and is correct, so the server automatically authenticates client again:
app.route("/private").get(
(req, res, next) => {
if (!req.session.authenticated) {
const authorization = req.get("Authorization");
if (authorization == null)
return authenticate(res); // see function definition below
const [ , credentialsRaw ] = authorization.split(" ");
const [ username, password ] = Buffer.from(credentialsRaw, "base64").toString("ascii").split(":");
if (username in users === false)
return authenticate(res);
if (password !== users[username].password) // I didn't bother with security
return authenticate(res);
req.session.authenticated = true;
}
next();
},
(req, res) => {
res.send(`<h1>Congratulations! You've accessed the private page! 👍</h1>`);
},
);
function authenticate(res) {
res.setHeader("WWW-Authenticate", `Basic realm="Access to the staging site"`);
res.status(401).send(`<h1>Unauthorized 😢!</h1>`)
}
So, it looks like HTTP Basic Authentication does not include logging out or expiring the credentials.
If anybody wants my opinion, it's a shame, actually.