Basic HTTP authentication with Node and Express 4 Basic HTTP authentication with Node and Express 4 express express

Basic HTTP authentication with Node and Express 4


Simple Basic Auth with vanilla JavaScript (ES6)

app.use((req, res, next) => {  // -----------------------------------------------------------------------  // authentication middleware  const auth = {login: 'yourlogin', password: 'yourpassword'} // change this  // parse login and password from headers  const b64auth = (req.headers.authorization || '').split(' ')[1] || ''  const [login, password] = Buffer.from(b64auth, 'base64').toString().split(':')  // Verify login and password are set and correct  if (login && password && login === auth.login && password === auth.password) {    // Access granted...    return next()  }  // Access denied...  res.set('WWW-Authenticate', 'Basic realm="401"') // change this  res.status(401).send('Authentication required.') // custom message  // -----------------------------------------------------------------------})

note: This "middleware" can be used in any handler. Just remove next() and reverse the logic. See the 1-statement example below, or the edit history of this answer.

Why?

  • req.headers.authorization contains the value "Basic <base64 string>", but it can also be empty and we don't want it to fail, hence the weird combo of || ''
  • Node doesn't know atob() and btoa(), hence the Buffer

ES6 -> ES5

const is just var .. sort of
(x, y) => {...} is just function(x, y) {...}
const [login, password] = ...split() is just two var assignments in one

source of inspiration (uses packages)


The above is a super simple example that was intended to be super short and quickly deployable to your playground server. But as was pointed out in the comments, passwords can also contain colon characters :. To correctly extract it from the b64auth, you can use this.

  // parse login and password from headers  const b64auth = (req.headers.authorization || '').split(' ')[1] || ''  const strauth = Buffer.from(b64auth, 'base64').toString()  const splitIndex = strauth.indexOf(':')  const login = strauth.substring(0, splitIndex)  const password = strauth.substring(splitIndex + 1)  // using shorter regex by @adabru  // const [_, login, password] = strauth.match(/(.*?):(.*)/) || []

Basic auth in one statement

...on the other hand, if you only ever use one or very few logins, this is the bare minimum you need: (you don't even need to parse the credentials at all)

function (req, res) {//btoa('yourlogin:yourpassword') -> "eW91cmxvZ2luOnlvdXJwYXNzd29yZA=="//btoa('otherlogin:otherpassword') -> "b3RoZXJsb2dpbjpvdGhlcnBhc3N3b3Jk"  // Verify credentials  if (  req.headers.authorization !== 'Basic eW91cmxvZ2luOnlvdXJwYXNzd29yZA=='     && req.headers.authorization !== 'Basic b3RoZXJsb2dpbjpvdGhlcnBhc3N3b3Jk')            return res.status(401).send('Authentication required.') // Access denied.     // Access granted...  res.send('hello world')  // or call next() if you use it as middleware (as snippet #1)}

PS: do you need to have both "secure" and "public" paths? Consider using express.router instead.

var securedRoutes = require('express').Router()securedRoutes.use(/* auth-middleware from above */)securedRoutes.get('path1', /* ... */) app.use('/secure', securedRoutes)app.get('public', /* ... */)// example.com/public       // no-auth// example.com/secure/path1 // requires auth


TL;DR:

express.basicAuth is gone
basic-auth-connect is deprecated
basic-auth doesn't have any logic
http-auth is an overkill
express-basic-auth is what you want

More info:

Since you're using Express then you can use the express-basic-auth middleware.

See the docs:

Example:

const app = require('express')();const basicAuth = require('express-basic-auth'); app.use(basicAuth({    users: { admin: 'supersecret123' },    challenge: true // <--- needed to actually show the login dialog!}));


A lot of the middleware was pulled out of the Express core in v4, and put into separate modules. The basic auth module is here: https://github.com/expressjs/basic-auth-connect

Your example would just need to change to this:

var basicAuth = require('basic-auth-connect');app.use(basicAuth('username', 'password'));