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

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Power BI Embedded Analytics — Part 2: Power BI Embedded Overview
  • Simplify Authorization in Ruby on Rails With the Power of Pundit Gem
  • Understanding the Identity Bridge Framework
  • In-App Browsers in Mobile Apps: Benefits, Challenges, Solutions

Trending

  • Scalability 101: How to Build, Measure, and Improve It
  • Fixing Common Oracle Database Problems
  • Enhancing Avro With Semantic Metadata Using Logical Types
  • Beyond Microservices: The Emerging Post-Monolith Architecture for 2025

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
20.9K 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: 'jack@example.com' } ] }
  , { id: 2, username: 'jill', password: 'birthday', displayName: 'Jill', emails: [ { value: 'jill@example.com' } ] }
];

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": "jack@example.com",
    "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

  • Power BI Embedded Analytics — Part 2: Power BI Embedded Overview
  • Simplify Authorization in Ruby on Rails With the Power of Pundit Gem
  • Understanding the Identity Bridge Framework
  • In-App Browsers in Mobile Apps: Benefits, Challenges, Solutions

Partner Resources

×

Comments

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

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

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 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: