npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

json-server-auth-login5

v1.0.0

Published

JWT authentication middleware for **[JSON Server](https://github.com/typicode/json-server)**

Downloads

3

Readme

🔐 JSON Server Auth

JWT authentication middleware for JSON Server

Because you also need a fake authentication & authorization flow for your prototyping.

Getting started

Install both JSON Server and JSON Server Auth :

# NPM
npm install -D json-server json-server-auth

# Yarn
yarn add -D json-server json-server-auth

Create a db.json file with a users collection :

{
  "users": []
}

Start JSON server (with JSON server Auth as middleware) :

json-server db.json -m ./node_modules/json-server-auth
# with json-server installed globally and json-server-auth installed locally
📢 but wait !

As a convenience, json-server-auth CLI exposes json-server bundled with its middlewares :

json-server-auth db.json
# with json-server-auth installed globally

It exposes and works the same for all JSON Server flags.

Authentication flow 🔑

JSON Server Auth adds a simple JWT based authentication flow.

Register 👥

Any of the following routes registers a new user :

  • POST /register
  • POST /signup
  • POST /users

email and password are required in the request body :

POST /register
{
  "email": "[email protected]",
  "password": "bestPassw0rd"
}

The password is encrypted by bcryptjs. The response contains the JWT access token (expiration time of 1 hour) :

201 Created
{
  "accessToken": "xxx.xxx.xxx"
}
Other properties

Any other property can be added to the request body without being validated :

POST /register
{
  "email": "[email protected]",
  "password": "bestPassw0rd",
  "firstname": "Olivier",
  "lastname": "Monge",
  "age": 32
}
Update

Any update to an existing user (via PATCH or PUT methods) will go through the same process for email and password.

Login 🛂

Any of the following routes logs an existing user in :

  • POST /login
  • POST /signin

login and password are required, of course :

POST /login
{
  "email": "[email protected]",
  "password": "bestPassw0rd"
}

The response contains the JWT access token (expiration time of 1 hour) :

200 OK
{
  "accessToken": "xxx.xxx.xxx"
}

JWT payload 📇

The access token has the following claims :

  • sub : the user id (as per the JWT specs).
  • email : the user email.

Authorization flow 🛡️

JSON Server Auth provides generic guards as route middlewares.

To handle common use cases, JSON Server Auth draws inspiration from Unix filesystem permissions, especialy the numeric notation.

  • We add 4 for read permission.
  • We add 2 for write permission.

Of course CRUD is not a filesystem, so we don't add 1 for execute permission.

Similarly to Unix, we then have three digits to match each user type :

  • First digit are the permissions for the resource owner.
  • Second digit are the permissions for the logged-in users.
  • Third digit are the permissions for the public users.

For example, 640 means that only the owner can write the resource, logged-in users can read the resource, and public users cannot access the resource at all.

The resource owner 🛀

A user is the owner of a resource if that resource has a userId property that matches his id property. Example:

// The owner of
{ id: 8, text: 'blabla', userId: 1 }
// is
{ id: 1, email: '[email protected]' }

Private guarded routes will use the JWT sub claim (which equals the user id) to check if the user actually owns the requested resource, by comparing sub with the userId property.

Except for the actual users collection, where the JWT sub claim must match the id property.

Guarded routes 🚥

Guarded routes exist at the root and can restrict access to any resource you put after them :

| Route | Resource permissions | | :----------: | :--------------------------------------------------------------------------------------------------- | | /664/* | User must be logged to write the resource. Everyone can read the resource. | | /660/* | User must be logged to write or read the resource. | | /644/* | User must own the resource to write the resource. Everyone can read the resource. | | /640/* | User must own the resource to write the resource. User must be logged to read the resource. | | /600/* | User must own the resource to write or read the resource. | | /444/* | No one can write the resource. Everyone can read the resource. | | /440/* | No one can write the resource. User must be logged to read the resource. | | /400/* | No one can write the resource. User must own the resource to read the resource. |

Examples

  • Public user (not logged-in) does the following requests :

| Request | Response | | :-------------------------------------- | :----------------- | | GET /664/posts | 200 OK | | POST /664/posts{text: 'blabla'} | 401 UNAUTHORIZED |

  • Logged-in user with id: 1 does the following requests :

| Request | Response | | :--------------------------------------------------------- | :-------------- | | GET /600/users/1Authorization: Bearer xxx.xxx.xxx | 200 OK | | GET /600/users/23Authorization: Bearer xxx.xxx.xxx | 403 FORBIDDEN |

Setup permissions 💡

Of course, you don't want to directly use guarded routes in your requests. We can take advantage of JSON Server custom routes feature to setup resource permissions ahead.

Create a routes.json file :

{
  "/users*": "/600/users$1",
  "/messages*": "/640/messages$1"
}

Then :

json-server db.json -m ./node_modules/json-server-auth -r routes.json
# with json-server installed globally and json-server-auth installed locally
📢 but wait !

As a convenience, json-server-auth CLI allows you to define permissions in a more succinct way :

{
  "users": 600,
  "messages": 640
}

Then :

json-server-auth db.json -r routes.json
# with json-server-auth installed globally

You can still add any other normal custom routes :

{
  "users": 600,
  "messages": 640,
  "/posts/:category": "/posts?category=:category"
}

Module usage 🔩

If you go the programmatic way and use JSON Server as a module, there is an extra step to properly integrate JSON Server Auth :

⚠️ You must bind the router property db to the created app, like the JSON Server CLI does, and you must apply the middlewares in a specific order.

const jsonServer = require('json-server')
const auth = require('json-server-auth')

const app = jsonServer.create()
const router = jsonServer.router('db.json')

// /!\ Bind the router db to the app
app.db = router.db

// You must apply the auth middleware before the router
app.use(auth)
app.use(router)
app.listen(3000)

Permisssions Rewriter

The custom rewriter is accessible via a subproperty :

const auth = require('json-server-auth')

const rules = auth.rewriter({
  // Permission rules
  users: 600,
  messages: 640,
  // Other rules
  '/posts/:category': '/posts?category=:category',
})

// You must apply the middlewares in the following order
app.use(rules)
app.use(auth)
app.use(router)

TODO 📜

  • [ ] Use JSON Server id and foreignKeySuffix parameters
  • [ ] Handle query params in list requests to secure guarded routes more precisely
  • [ ] Allow configuration of :
    • [ ] Users collection name
    • [ ] Minimum password length
    • [ ] JWT expiry time
    • [ ] JWT property name in response
  • [ ] Implement JWT Refresh Token
  • [ ] Possibility to disable password encryption ?