Published: September 24 2018
Last updated: September 10 2020

NodeJS - Basic Authentication Tutorial with Example API

Tutorial built with Node.js

Other versions available:

In this tutorial we'll go through a simple example of how to implement Basic HTTP Authentication in a Node.js API with JavaScript.

The example API has just two endpoints/routes to demonstrate authenticating and accessing a restricted route with basic authentication:

  • /users/authenticate - public route that accepts HTTP POST requests containing the username and password in the body. If the username and password are correct then the user details are returned.
  • /users - secure route that accepts HTTP GET requests and returns a list of all the users in the application if the HTTP Authorization header contains valid basic authentication credentials. If there are no basic auth credentials or the credentials are invalid then a 401 Unauthorized response is returned.

The tutorial project is available on GitHub at https://github.com/cornflourblue/node-basic-authentication-api.

Update History:


Tutorial Contents


Run the Node Basic Authentication API Locally

  1. Install Node.js and npm from https://nodejs.org.
  2. Download or clone the tutorial project code from https://github.com/cornflourblue/node-basic-authentication-api
  3. Install all required npm packages by running npm install from the command line in the project root folder (where the package.json is located).
  4. Start the api by running npm start (or npm run start:dev to start with nodemon) from the command line in the project root folder, you should see the message Server listening on port 4000. Follow the instructions below to test with Postman or hook up with one of the example single page applications available (React, Angular, Vue or Blazor).


Test the Node.js Basic Authentication API with Postman

Postman is a great tool for testing APIs, you can download it at https://www.getpostman.com/.

Below are instructions on how to use Postman to authenticate a user with the api, and then make an authenticated request with basic authentication credentials to retrieve a list of users from the api.

How to authenticate a user with Postman

To authenticate a user with the basic authentication api and follow these steps:

  1. Open a new request tab by clicking the plus (+) button at the end of the tabs.
  2. Change the http request method to "POST" with the dropdown selector on the left of the URL input field.
  3. In the URL field enter the address to the authenticate route of your local API - http://localhost:4000/users/authenticate.
  4. Select the "Body" tab below the URL field, change the body type radio button to "raw", and change the format dropdown selector to "JSON (application/json)".
  5. Enter a JSON object containing the test username and password in the "Body" textarea:
    {
        "username": "test",
        "password": "test"
    }
  6. Click the "Send" button, you should receive a "200 OK" response containing the user details in the response body, this indicates that the username and password are correct.

Here's a screenshot of Postman after the request is sent and the user has been authenticated:


How to make an authenticated request to retrieve all users

To make an authenticated request using basic authentication credentials, follow these steps:

  1. Open a new request tab by clicking the plus (+) button at the end of the tabs.
  2. Change the http request method to "GET" with the dropdown selector on the left of the URL input field.
  3. In the URL field enter the address to the users route of your local API - http://localhost:4000/users.
  4. Select the "Authorization" tab below the URL field, change the type to "Basic Auth" in the type dropdown selector, enter test into the "Username" field and test into the "Password" field.
  5. Click the "Send" button, you should receive a "200 OK" response containing a JSON array with all the user records in the system (just the one test user in the example).

Here's a screenshot of Postman after making an authenticated request to get all users:


Run a React client app with the Node Basic Authentication API

For full details about the example React application see the post React - Basic HTTP Authentication Tutorial & Example. But to get up and running quickly just follow the below steps.

  1. Download or clone the React tutorial code from https://github.com/cornflourblue/react-basic-authentication-example
  2. Install all required npm packages by running npm install from the command line in the project root folder (where the package.json is located).
  3. Remove or comment out the 2 lines below the comment // setup fake backend located in the /src/index.jsx file.
  4. Start the application by running npm start from the command line in the project root folder, this will launch a browser displaying the React example application and it should be hooked up with the Node Basic Authentication API that you already have running.


Run an Angular 9 client app with the Node Basic Authentication API

For full details about the example Angular 9 application see the post Angular 9 - Basic HTTP Authentication Tutorial & Example. But to get up and running quickly just follow the below steps.

  1. Download or clone the Angular 9 basic auth tutorial code from https://github.com/cornflourblue/angular-9-basic-authentication-example
  2. Install all required npm packages by running npm install from the command line in the project root folder (where the package.json is located).
  3. Remove or comment out the line below the comment // provider used to create fake backend located in the /src/app/app.module.ts file.
  4. Start the application by running npm start from the command line in the project root folder, this will launch a browser displaying the Angular example application and it should be hooked up with the Node Basic Authentication API that you already have running.


Run a VueJS client app with the Node Basic Auth API

For full details about the example Vue.js application see the post Vue.js - Basic HTTP Authentication Tutorial & Example. But to get up and running quickly just follow the below steps.

  1. Download or clone the VueJS tutorial code from https://github.com/cornflourblue/vue-basic-authentication-example
  2. Install all required npm packages by running npm install from the command line in the project root folder (where the package.json is located).
  3. Remove or comment out the 2 lines below the comment // setup fake backend located in the /src/index.js file.
  4. Start the application by running npm start from the command line in the project root folder, this will launch a browser displaying the VueJS example application and it should be hooked up with the Node Basic Authentication API that you already have running.


Run a Blazor WebAssembly (WASM) client app with the Node.js Basic Auth API

For full details about the example Blazor application see the post Blazor WebAssembly - Basic HTTP Authentication Tutorial & Example. But to get up and running quickly just follow the below steps.

  1. Install the .NET Core SDK from https://www.microsoft.com/net/download/core.
  2. Download or clone the tutorial project code from https://github.com/cornflourblue/blazor-webassembly-basic-authentication-example
  3. Change the "fakeBackend" setting to "false" in the /wwwroot/appsettings.json file.
  4. Start the app by running dotnet run from the command line in the project root folder (where the BlazorApp.csproj file is located)
  5. Open a new browser tab and navigate to the URL http://localhost:5000, the Blazor app should be hooked up with the Node.js Basic Auth API that you already have running.

NOTE: To enable hot reloading during development so the app automatically restarts when a file is changed, start the app with the command dotnet watch run.


Node Basic Authentication Project Structure

The project is structured into "feature folders" (users) "non-feature / shared component folders" (_helpers). Shared component folders contain code that can be used by multiple features and other parts of the application, and are prefixed with an underscore to group them together so it's easy to see what's what at a glance.

The example only contains the single users feature, but this can be easily extended to handle any other feature by copying the users folder and following the same pattern.

 

Node Helpers Folder

Path: /_helpers

The helpers folder contains all the bits and pieces that don't fit into other folders but don't justify having a folder of their own.

 

Node Basic Authentication Verification Middleware

Path: /_helpers/basic-auth.js

The node basic authentication middleware checks that the basic authentication credentials (base64 encoded username & password) received in the http request from the client are valid before allowing access to the API, if the auth credentials are invalid a 401 Unauthorized response is sent to the client.

const userService = require('../users/user.service');

module.exports = basicAuth;

async function basicAuth(req, res, next) {
    // make authenticate path public
    if (req.path === '/users/authenticate') {
        return next();
    }

    // check for basic auth header
    if (!req.headers.authorization || req.headers.authorization.indexOf('Basic ') === -1) {
        return res.status(401).json({ message: 'Missing Authorization Header' });
    }

    // verify auth credentials
    const base64Credentials =  req.headers.authorization.split(' ')[1];
    const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
    const [username, password] = credentials.split(':');
    const user = await userService.authenticate({ username, password });
    if (!user) {
        return res.status(401).json({ message: 'Invalid Authentication Credentials' });
    }

    // attach user to request object
    req.user = user

    next();
}
 

Node Global Error Handler Middleware

Path: /_helpers/error-handler.js

The global error handler is used catch all errors and remove the need for redundant error handler code throughout the application. It's configured as middleware in the main server.js file.

module.exports = errorHandler;

function errorHandler(err, req, res, next) {
    if (typeof (err) === 'string') {
        // custom application error
        return res.status(400).json({ message: err });
    }

    // default to 500 server error
    return res.status(500).json({ message: err.message });
}
 

Node Users Folder

Path: /users

The users folder contains all code that is specific to the users feature of the api.

 

Node User Service

Path: /users/user.service.js

The user service contains a method for authenticating user credentials and a method for getting all users in the application.

I hardcoded the array of users in the example to keep it focused on basic HTTP authentication, in a production application it is recommended to store user records in a database with hashed passwords. For an extended example that uses JWT, includes support for user registration and stores data in MongoDB check out NodeJS + MongoDB - Simple API for Authentication, Registration and User Management.

The top of the file contains the exported service method definitions so it's easy to see all methods at a glance, the rest of the file contains the method implementations.

// users hardcoded for simplicity, store in a db for production applications
const users = [{ id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User' }];

module.exports = {
    authenticate,
    getAll
};

async function authenticate({ username, password }) {
    const user = users.find(u => u.username === username && u.password === password);
    if (user) {
        const { password, ...userWithoutPassword } = user;
        return userWithoutPassword;
    }
}

async function getAll() {
    return users.map(u => {
        const { password, ...userWithoutPassword } = u;
        return userWithoutPassword;
    });
}
 

Node Users Controller

Path: /users/users.controller.js

The users controller defines all user routes for the api, the route definitions are grouped together at the top of the file and the implementations are below.

Express is the web server used by the api, it's one of the most popular web application frameworks for Node.js.

const express = require('express');
const router = express.Router();
const userService = require('./user.service');

// routes
router.post('/authenticate', authenticate);
router.get('/', getAll);

module.exports = router;

function authenticate(req, res, next) {
    userService.authenticate(req.body)
        .then(user => user ? res.json(user) : res.status(400).json({ message: 'Username or password is incorrect' }))
        .catch(err => next(err));
}

function getAll(req, res, next) {
    userService.getAll()
        .then(users => res.json(users))
        .catch(err => next(err));
}
 

Node Main Server Entrypoint

Path: /server.js

The server.js file is the entry point into the api, it configures application middleware, binds controllers to routes and starts the Express web server for the api.

require('rootpath')();
const express = require('express');
const app = express();
const cors = require('cors');
const bodyParser = require('body-parser');
const basicAuth = require('_helpers/basic-auth');
const errorHandler = require('_helpers/error-handler');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cors());

// use basic HTTP auth to secure the api
app.use(basicAuth);

// api routes
app.use('/users', require('./users/users.controller'));

// global error handler
app.use(errorHandler);

// start server
const port = process.env.NODE_ENV === 'production' ? 80 : 4000;
const server = app.listen(port, function () {
    console.log('Server listening on port ' + port);
});

 


Need Some NodeJS Help?

Search fiverr for freelance NodeJS developers.


Follow me for updates

On Twitter or RSS.


When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Comments


Supported by