node package manager
Easy sharing. Manage teams and permissions with one click. Create a free org ยป

@mitchallen/microservice-rights

@ mitchallen / microservice-rights

A module for defining rights to access a URL

This module works in association with other modules based on the @mitchallen/microservice-core module. For a background on the core and microservices, visit the core npm page.


Disclaimer

The author makes no claims that this system is secure. Use at your own risk.


Installation

You must use npm 2.7.0 or higher because of the scoped package name.

$ npm init
$ npm install @mitchallen/microservice-rights --save

Usage

Step 1: Setup npm dependencies

Open up a terminal window, create a folder for our app and change to it. Then setup your npm package dependencies.

$ npm init
$ npm install @mitchallen/microservice-rights --save
$ npm install @mitchallen/microservice-token --save
$ npm install @mitchallen/microservice-core --save

Step 2: Setup a secret key for your token

Create an environment variable holding your secret key. This is used by the token middleware to encrypt the user role.

$ export SECRET=mySecret

Step 3: Create a file called index.js

Create a file called index.js and add the following:

"use strict";

 let secret = process.env.SECRET;
 let tokenHandler = require('@mitchallen/microservice-token')(secret);
 let rightsWare = require('@mitchallen/microservice-rights');

Step 4: Create a Rights Table

Define a table with roles and a list of what other roles can access something at that level.

Normally you would pull this from a shared resource. To keep things simple, we just hard-code it in this example.

let table = {
    roles: [ "none", "admin", "user", "public" ],
    rights: {
        /// required rights : list of who can access links marked with required rights]
        // link marked admin can only be accessed by admin
        "admin"  : [ "admin" ], 
        // link marked user can be accessed by admin and user
        "user"   : [ "admin", "user" ], 
        // link marked public can be accessed by all
        "*"      : [ "admin", "user", "*" ]    
    }
};

What this mean:

  • Only admins can access a URL for admins.
  • Admins and users can access a URL for users
  • Anyone can access a URL for wildcard ('*')
  • No one can access a URL designated as none.

Step 5: Define your Web service

Using @mitchallen/microservice-core, setup a Web service using our rights manager and token middleware.

The names used above are completely arbitrary. You can use whatever names you like.

    var authorization = {
        access: "admin",
  		table: table
	};

    var options = {
  		service: {
            // Get the name and version from package.json
            name: require("./package").name,
            version: require("./package").version,
            verbose: true,
            port: process.env.SERVICE_PORT || 8004,
            apiVersion: process.env.API_VERSION || '/v1',
            method: function (info) {
                var router = info.router;
                router.use(tokenHandler);
                router.get('/admin/home', 
                    // Test authorization
                    rightsWare.isAuthorized( authorization ),
                    function (req, res) {
                        var data = {
                            type: "restricted",
                            status: "You got in!",
                        };
                        res.json(data);
                    });
                return router;
            }
        }
    };

    // Pass the options to microservice-core
	module.exports = require('@mitchallen/microservice-core')(options);

Save index.js

Type the following at the command line:

$ node index.js

Leave that running.

Step 6: Create the Key Master

Normally we might generate a token from a login service. But since we don't have a login service, we need to fake it.

Open up a new terminal window and switch to the same directory.

Since we didn't take steps to make our environment variable permanent, you will need to recreate it for this new window.

$ export SECRET=mySecret

Create a file called key-master.js, add the following and save it:

"use strict";

let secret = process.env.SECRET || "test-server"; 
let port = process.env.SERVICE_PORT || 8004;

let jwt = require('jwt-simple');

let roles = ['admin','user','*'];

let bar = Array(50).join('-');

roles.forEach(function(value) {
    let testData = {
        user: 'Jack',
        role: value
    }

    var token = jwt.encode( testData, secret)

    console.log("%s\n\ntoken:\n\n%s\n\n%s", bar, token, JSON.stringify(testData));

console.log(
    '\ncurl -i -X GET -H "x-auth: ' + token + '" ' +
    '-H "Content-Type: application/json" http://localhost:' + port + '/v1/admin/home\n\n');
}); 

console.log(bar);

Step 7: Generate the tokens and curl commands

At the command line, type:

$ node key-master.js

It will produce output like this (note that for your secret key the tokens will be different!):

-------------------------------------------------

token: 

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiSmFjayIsInJvbGUiOiJhZG1pbiJ9.rM2EJZ4s1StvcoeMh9K6P1LFWhlCwMKsGsAVH11z93M

{"user":"Jack","role":"admin"}

curl -i -X GET -H "x-auth: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiSmFjayIsInJvbGUiOiJhZG1pbiJ9.rM2EJZ4s1StvcoeMh9K6P1LFWhlCwMKsGsAVH11z93M" -H "Content-Type: application/json" http://localhost:8004/v1/admin/home


-------------------------------------------------

token:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiSmFjayIsInJvbGUiOiJ1c2VyIn0.Y58tW4t4uYZPUX3iP2qFCHAcTOtgUPcQjD3Kds1f0Ik

{"user":"Jack","role":"user"}

curl -i -X GET -H "x-auth: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiSmFjayIsInJvbGUiOiJ1c2VyIn0.Y58tW4t4uYZPUX3iP2qFCHAcTOtgUPcQjD3Kds1f0Ik" -H "Content-Type: application/json" http://localhost:8004/v1/admin/home


-------------------------------------------------

token:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiSmFjayIsInJvbGUiOiIqIn0.G0ivI5iG-_f6km_vV-xBHrT_lWN5v8agyapJfDnm9ts

{"user":"Jack","role":"*"}

curl -i -X GET -H "x-auth:     eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiSmFjayIsInJvbGUiOiIqIn0.G0ivI5iG-_f6km_vV-xBHrT_lWN5v8agyapJfDnm9ts" -H "Content-Type: application/json" http://localhost:8004/v1/admin/home


-------------------------------------------------

Based on whatever secret key you defined it will generate a token and curl command for each role.

Step 8: Test rights access

Copy and paste the curl commands for each role into the second terminal window.

For example (your token may be different based on your secret key):

curl -i -X GET -H "x-auth: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiSmFjayIsInJvbGUiOiJhZG1pbiJ9.rM2EJZ4s1StvcoeMh9K6P1LFWhlCwMKsGsAVH11z93M" -H "Content-Type: application/json" http://localhost:8004/v1/admin/home

For the admin role you should get a HTTP 200 OK response like this:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 44
Connection: keep-alive

For the other roles you should get a HTTP 401 Unauthorized response like this.

HTTP/1.1 401 Unauthorized
X-Powered-By: Express
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8
Content-Length: 16
Connection: keep-alive

The code above can be found in the examples / access folder.

Testing

To test, go to the root folder and type (sans $):

$ npm test

Repo(s)


Contributing

In lieu of a formal style guide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code.


Version History

Version 0.1.0 release notes

  • initial release