What is Basic Auth? With ExpressJS example
Table of content
- Introduction to Basic Authentication
- Implementing Basic Authentication with Express.js
- Best Practices and Security Considerations
- Conclusion
Implementing Basic Authentication with Express.js
In this chapter, I want to show you how to implement basic auth in your Express.js application. I will assume that you have already written an Express.js server, and we will write middleware to protect your endpoints from unauthorized access. Additionally, we will not use a library, but develop the middleware ourselves. This is purely to demonstrate how basic auth works. Nevertheless, I recommend using existing libraries or mechanisms for your implementation.
Implementation of the middleware
⚠ Note: This middleware is a basic example for educational purposes only and should not be used in a deployed application. For production use, employ a framework that addresses a wider range of security concerns.
Lets just start with some simple variables we will use later
// the name of our realm, it can be anything
const basicAuthRealm = 'protected area'
// our dummy user table
const userTable = [
{username: 'admin', password: 'admin'},
]
To create a middleware, we have to do the following steps:
We need to get what's written in the Authorization header and check if it is set.
We need to check if the schema is "Basic".
Afterwards, we need to decode the credentials which are encoded in base64.
Split the username from the password by ":", but consider that the password can contain a ":" too.
Check if credentials match with one from the table.
If not, send an unauthorized response with "WWW-Authenticate" header.
function basicAuthMiddleware(req: Request, res: Response, next: () => void) {
// Get the authorization header
const authHeader = req.headers['authorization']
if (authHeader) {
const [authSchema, authCredentials] = authHeader.split(' ')
// We only allow "basic" as schema, alternatives would e.g. be a "bearer" auth
// And credentials should be given
if (authSchema.toLowerCase() === 'basic' && authCredentials) {
const buffer = Buffer.from(authCredentials, 'base64')
const pattern = new RegExp(/^([^:]+):(.+)$/)
const result = pattern.exec(buffer.toString())
/*
* Note: simply using .split(':') is not enough, because : is allowed to be used in the password
*/
if (result) {
const username = result[1]
const password = result[2]
for (const user of userTable) {
if (user.username === username && user.password === password) {
return next()
}
}
}
}
}
res.set('WWW-Authenticate', `Basic realm="${basicAuthRealm}"`)
res.status(401).send('Unauthorized')
}
Using the middleware
Now we just need to pass the middleware to the express app.
const app = express()
app.use(basicAuthMiddleware)
app.get('/', (req, res) => {
res.send('Hello World')
})
app.listen(3000, () => {
console.log('Server is running at <http://localhost:3000>')
})
Testing your middleware
Now start your server and open the website in your browser. A basic auth form should appear. With random credentials, you should not be able to log in. However, the username "admin" and the password "admin" should work, and you'll see the "Hello World" message.
For your real applications
When you want to use basic auth in your real application, you could use libraries like express-basic-auth. However, I couldn't find a library with many stars on GitHub. Another, more professional approach would be to use a proxy in between, e.g., Nginx, which can then handle basic auth.