DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Your API Authentication Isn’t Broken; It’s Quietly Failing in These 6 Ways
  • Context-Aware Authorization for AI Agents
  • The ID That Costs Millions: Why API Authorization Failures Keep Winning
  • Integrating OpenID Connect (OIDC) Authentication in Angular and React

Trending

  • Why Google Data Migration Gets Stuck at 99%: Causes and Proven Fixes
  • What Is Plagiarism? How to Avoid It and Cite Sources
  • Slopsquatting: Building a Scanner That Catches AI-Hallucinated Packages Before They Reach Production
  • Architecting Sub-Microsecond HFT Systems With C++ and Zero-Copy IPC

Basic Authentication for json-server

This article will share an approach for adding authentication to a json-server using an Express middleware component called Passport.

By 
Mitch Dresdner user avatar
Mitch Dresdner
·
May. 03, 18 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
21.4K Views

Join the DZone community and get the full member experience.

Join For Free

Summary

In my last DZone article on Zero Code REST with json-server I showed you how to stand up a REST server with minimal effort and no coding.

While this approach may work well in many situations, you often find that you'll need to extend capabilities, so you'll soon roll up your sleeves and start bending some code. The fun stuff!

This article will share an approach for adding authentication to a json-server using a simple, unobtrusive Express middleware component called Passport.

Architecture

Most sites require users to register and then use their credentials for access. Passport provides the layers necessary for authenticating claims made by users logging in to the site.

User Registration

User Registration

Basic Authentication is the simplest form of authenticating users, consisting of a username and a secret password. Being the simplest, it's arguably also the weakest form and vulnerable to intercept and exploitation when not used with secure transports.

The intent of this article is to share how we can start moving from plain text unauthenticated methods of communicating with our json-server to more robust solutions. Passport provides an extensible set of plugins known as strategies which will help you to do just that. At the time of writing this article, there are nearly 500 authentication strategies to choose from including:

  • Basic Authentication

  • Facebook

  • Twitter

  • Google

  • LinkedIn

Strategies can range from verifying a username and password credentials, delegated authentication using OAuth (using Facebook or Twitter), or federated authentication using OpenID.

Passport Strategy

Passport strategies are generally of the following form:

passport.use(new Strategy(
  function(username, password, cb) {  // <1>
    db.users.findByUsername(username, function(err, user) {  // <2>
      if (err) { return cb(err); }  // <3>
      if (!user) { return cb(null, false); }  // <4>
      if (user.password != password) { return cb(null, false); } // <5>
      return cb(null, user);
    });
  }));

Example Passport Strategy

  1. Authentication credentials

  2. Callback to verify access

  3. Error handling

  4. User Verification

  5. Password authentication

We'll now integrate passport authentication with the json-server we created in the last article.

CAUTION: For the sake of brevity and focusing on authentication, this example doesn't use TLS as any real-world application should.

Configuring User Authentication

Passport author Jared Hanson provides us with many a good example of Strategy implementation; and, as good OO practitioners we'll follow the mantra to reuse rather than reinvent, leveraging his Basic Authentication example.

Our new folder hierarchy now includes a db folder, simulating a database containing authentication credentials.

Image title

Passport authentication support

index.js Listing

exports.users = require('./users');

users.js Listing

var records = [
    { id: 1, username: 'jack', password: 'secret', displayName: 'Jack', emails: [ { value: '[email protected]' } ] }
  , { id: 2, username: 'jill', password: 'birthday', displayName: 'Jill', emails: [ { value: '[email protected]' } ] }
];

exports.findByUsername = function(username, cb) {
  process.nextTick(function() {
    for (var i = 0, len = records.length; i < len; i++) {
      var record = records[i];
      if (record.username === username) {
        return cb(null, record);
      }
    }
    return cb(null, null);
  });
}

Configuring npm Packages

In our earlier Zero Code example, we were able to start the json-server with static
assets in our project hierarchy. As we add custom code, we'll need a way of letting npm
know about our project dependencies. This is accomplished by adding package.json.

{
  "name": "custom-json-server",
  "version": "1.0.0",
  "description": "Custom json-server",
  "main": "server.js",
  "dependencies": {
    "json-server": "^0.12.1",     // <1>
    "passport": "^0.2.2",         // <2>
    "passport-http": "^0.3.0"     <
  },
  "devDependencies": {
    "json-server": "^0.12.1"

  },
  "scripts": {
    "serve": "node server.js --watch ./json/db.json",// <3>
    "test":       "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "json",
    "api"
  ],
  "author": "M. Dresdner",
  "license": "MIT"
}

Our package.json includes:

  1. json-server dependencies.

  2. Passport dependencies.

  3. The script for starting our server.

After creating the package.json we'll need to install the required packages. This is accomplished by running the npm install command, or the short form, npm i.

npm install

npm install

You should see npm pull down all the required packages and save them into the folder, node_modules.

With json-server and passport packages installed we turn our attention toward creating our
custom code json-server.

Configuring Server.json

Our customized rendition of json-server allows for additional middleware products in our json-server implementation. To add the Basic Authentication support, we start with the sample code described in the Module section of the json-server website and add our references to Passport.

const jsonServer = require('json-server')
const server = jsonServer.create()
const path = require('path')
const router = jsonServer.router(path.join(__dirname, './json/db.json'))

const middlewares = jsonServer.defaults()

var passport = require('passport');   // <1>
var Strategy = require('passport-http').BasicStrategy;
var db = require('./db/index');


// Configure the Basic strategy for use by Passport.    // <2>
passport.use(new Strategy(
  function(username, password, cb) {
    db.users.findByUsername(username, function(err, user) {
      if (err) { return cb(err); }
      if (!user) { return cb(null, false); }
      if (user.password != password) { return cb(null, false); }
      return cb(null, user);
    });
  }));

// http -a jack:secret localhost:3000/email     // <3>
server.get('/email',
  passport.authenticate('basic', { session: false }),
  function(req, res) {
    res.json({ username: req.user.username, email: req.user.emails[0].value });
  });

server.use(middlewares)


// http localhost:3000/wines
server.use(router)
server.listen(3000, () => {
  console.log('JSON Server is running on 3000')
})

server.js

In the above code, we are:

  1. Bringing in Passport support.

  2. Configuring our Basic Authentication strategy.

  3. Adding a new Express handler for authenticating a new request.

With the integration of Passport with json-server complete, Passport should now be configured to validate a new route request to /email.

Let's start up the json-server and see if we broke anything in our latest refactorings.

npm run serve

Start json-server

Since we now have a custom json-server implementation, we start it using the script (above) that we added earlier in our package.json.

When the json-server starts you see the message JSON Server is running on 3000.

We can now send some test messages with httpie.

http localhost:3000/wines

Regression Testing

If all went well, you should see a familiar response to the all wines request from json-server.

http -a jack:secret localhost:3000/email

Authentication Test

If all went well, you should see the following response:

HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 55
Content-Type: application/json; charset=utf-8
Date: Mon, 30 Apr 2018 18:06:27 GMT
ETag: W/"37-lew270BaMoufxDP6PMJe/Pp2Pys"
X-Powered-By: Express

{
    "email": "[email protected]",
    "username": "jack"
}

Authentication Response

Next, we'll mess with the password and try again.

http -a jack:Xsecret localhost:3000/email

Authentication Failure

As expected, we get an authentication failure.

HTTP/1.1 401 Unauthorized
Connection: keep-alive
Content-Length: 12
Date: Mon, 30 Apr 2018 18:08:45 GMT
WWW-Authenticate: Basic realm="Users"
X-Powered-By: Express

Unauthorized

Authentication Failure Response

That was useful and a bit of fun, for your next steps I expect you may want to try another Passport Strategy like Google or LinkedIn authentication!

Passport's pluggable authentication greatly simplifies a complex, arduous, and oft times error-prone process.

I hope you've enjoyed reading this article as much as I have writing it and am looking forward to your feedback.

authentication

Opinions expressed by DZone contributors are their own.

Related

  • Your API Authentication Isn’t Broken; It’s Quietly Failing in These 6 Ways
  • Context-Aware Authorization for AI Agents
  • The ID That Costs Millions: Why API Authorization Failures Keep Winning
  • Integrating OpenID Connect (OIDC) Authentication in Angular and React

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook