Search code examples
javascriptnode.jsexpressbasic-authentication

How to expire Authorization header in request?


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>`)
}

Solution

  • 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.