Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Role based authentication in HapiJS

I am working on a rest API first project written with HapiJS. After the login process the user gets a token to pass in the header of every request. Users have different roles (admin, standard, guest, partners) and some Api endpoint are reachable only by users with a certain role. Someone could help me in defining this check in a nice way, so without writing the check everytime inside the route?

like image 972
Mino Avatar asked Mar 14 '15 18:03

Mino


1 Answers

Scopes

You can use scopes in hapi. When you authenticate the request by checking the header, you can set the scope property of the user's credentials:

var validateFunc = function (username, password, callback) {

    ... // Your logic here

    return callback(null, true, {scope: 'admin'});
};

When defining a route you can set the scopes which are permitted to that endpoint in the config.auth.scope property:

server.route({
    ...
    config: {
        auth: {
            strategy: 'simple', 
            scope: ['user', 'admin']
        },
    }
    ...
});

Now, only users who are authenticated with the scope of user or admin, will be able to access that route.

Process

  1. Decide on some scopes (admin, superuser, guest etc)
  2. Configure your authentication routine to correctly set the scope on the user's credentials
  3. Configure your routes by setting the config.auth.scope to whomever is allowed to access it

Runnable Example

var Hapi = require('hapi');

var server = new Hapi.Server();
server.connection({ port: 4000 });

server.register(require('hapi-auth-basic'), function (err) {

    if(err) {
        throw err;
    }

    server.auth.strategy('simple', 'basic', {
        validateFunc: function (username, password, callback) {

            if (username === 'admin') {
                return callback(null, true, {scope: 'admin'}); // They're an `admin`
            }
            if (username === 'user') {
                return callback(null, true, {scope: 'user'}); // They're a `user`
            }
            return callback(null, false);
        }
    });

    server.route([{
            config: {
                auth: {
                    strategy: 'simple', 
                    scope: ['admin']                    // Only admin
                },
            },
            method: 'GET',
            path: '/admin',
            handler: function(request, reply) {

                reply('Admin page');
            }
        }, {
            config: {
                auth: {
                    strategy: 'simple', 
                    scope: ['user', 'admin']            // user or admin
                },
            },
            method: 'GET',
            path: '/user',
            handler: function(request, reply) {

                reply('User page');
            }
        }
    ]);

    server.start(function () {
        console.log('Started server');
    });
});
like image 136
Matt Harrison Avatar answered Oct 05 '22 18:10

Matt Harrison