Introduction

This article is about how to do authentication with node express.

Add packages to your project

package.json

{
    "dependencies": {
        "express": "^4.17.1",
        "body-parser": "^1.19.0",
        "passport": "^0.4.1",
        "passport-http": "^0.3.0",
        "passport-strategy": "^1.0.0",
    }
}

Create Auth module

Create an Auth.js module.

const passport = require('passport');
const Strategy = require('passport-http').DigestStrategy;

const STRATEGY_DIGEST = 'digest';

class Auth {
    constructor(dbManager) {
        this._dbManager = dbManager;
        this._passport = passport;
        this.init();
    }

    init() {
        this._passport.use(STRATEGY_DIGEST, new Strategy({ qop: 'auth' },
            async (username, cb) => {
                const users = await this._dbManager.userDao.findUsers(username);
                if (users.length > 0) {
                    cb(null, users[0].username, users[0].password);
                } else {
                    cb(null, false);
                }
            }));
    }

    get digestAuth() {
        return this._passport.authenticate(STRATEGY_DIGEST, { session: false });
    }
}

module.exports = Auth;

If your service is deployed on cloud with envoy proxy, the DigestStrategy return 400 BadRequest, you have to customize the digest.js of passport-http library.

Put the following code to digest.js url checking part to deal with envoy proxy problem.

const envoyOriginalPath = req.headers['x-envoy-original-path'];
const url = envoyOriginalPath || req.originalUrl || req.url;
if (url !== creds.uri) {
    return this.fail(400);
}

Use auth strategy on API

const express = require('express');
const bodyParser = require('body-parser');
const Auth = require('./auth/Auth');

const app = express();
app.use(bodyParser.json());

const userService = new UserService();
app.get('/api/user/fetchUsers', auth.digestAuth, userService.fetchUsers.bind(userService)));

// start server
app.listen(8080, () => console.log(`service is listening on port 8080`));

Request API from client side

If client side is node.js, use request library to do api request.

request.post({
        uri: `http://localhost:8080/${api}`,
        headers: {
            'Content-Type': 'application/json',
        },
        body: {
            // params
        },
        json: true,
        auth: {
            user: process.env.USER_NAME,
            pass: process.env.PASSWORD,
            sendImmediatey: false, // Digest authentication is supported, but it only works with sendImmediately set to false (sendImmediately defaults to true, which causes a basic authentication header to be sent).
        },
    }, (error, response, body) => {
        // deal with response or error 
    });

References

Bad request on digest authentication (User: false)