How to apply ACLs to loopback application

Written by ahsan.ayaz | Published 2017/03/15
Tech Story Tags: nodejs | javascript | loopback | backend-development | web-development

TLDRvia the TL;DR App

There’s no need to mention how quickly everyone has adopted Node.js for application development and that too still continues.

According to Stackoverflow.com’s survey of 2016, Javascript is the most trending technology along with Node.JS gaining significant popularity too.

Also, we can see how many customers use Node.js in production in the stats on the following site https://siftery.com/nodejs . There’re multiple giants using Node.js for their applications some of them are :

Curios what parts they cover using Node.js? Here’s one about how LinkedIn is using Node.js in their application :

Exclusive: How LinkedIn used Node.js and HTML5 to build a better, faster app_This morning, LinkedIn launched its gorgeously overhauled mobile app. We've already told you all about the new features…_venturebeat.com

While there are a lot of packages/tools you’ll be using developing with Node.js, i.e. Hapi/Koa/Koa2/Express, there’s Loopback too which is gaining huge popularity due to its diversity and amazing features.

A little info about Loopback is that it is created by folks at Strongloop which is an IBM company. It allows you to create strong & flexible APIs and models in no time. Not to mention it has great things to work with i.e. the connectors and components available.

With that said, lets jump to the ACLs now.

ACLs

LoopBack uses access control lists (ACLs) to control who can access what data.

With ACLs, you can restrict data access to models i.e. the api methods however you want. The way it works is that Loopback uses two collections, Role and RoleMapping. You can create custom roles too but there’re some roles which loopback itself provides out of the box. I.e. $everyone, $authenticated, $unauthenticated etc.

Lets assume that you have a customer support application having following models:

  1. AppUser (extended from User)
  2. Categories

We’ll create some custom roles (in boot/script.js):

// Assuming...// employeeUsers[] contains the employees// adminUsers[] contains the admins

Role.create({      name: 'admin'    }, function(err, role) {      if (err) cb(err);      adminUsers.forEach(function(admin){          //make bob an admin          role.principals.create({            principalType: RoleMapping.USER,            principalId: admin.id          }, function(err, principal) {              cb(err);          });      });     });Role.create({      name: 'employee'    }, function(err, role) {      if (err) cb(err);      

Suppose we have the following apis :

  1. Get categories = GET /api/categories
  2. Get category by id = GET /api/categories/:cat_id
  3. Create category = Post /api/categories

We want that only the admin can access ‘Get categories’ call and the authenticated users (employees) should access the ‘Get category by id’ call however employees should not be allowed to create a category. So here’s what we’ll do. We’ll use the loopback’s generator to create an ACL.

First, deny access to the categories api for everyone

$ lb acl

? Select the model to apply the ACL entry to: Category? Select the ACL scope: All methods and properties? Select the access type: All (match all types)? Select the role: All users? Select the permission to apply: Explicitly deny access

Next, we’ll allow the admin to access all the category api.

$ lb acl? Select the model to apply the ACL entry to: Category? Select the ACL scope: All methods and properties? Select the role: other? Enter the role name : admin? Select the permission to apply: Explicitly grant access

Next, we’ll allow only the employee to access the category by id call.

$ lb acl

? Select the model to apply the ACL entry to: Category? Select the ACL scope: A single method? Enter the method name: findById? Select the role: other? Enter the role name : employee? Select the permission to apply: Explicitly grant access

After executing the above commands, the ACLs in our category.json should look like this :

"acls": [  {    "accessType": "*",    "principalType": "ROLE",    "principalId": "$everyone",    "permission": "DENY"  },  

Conclusion

The summarized key-points about ACLs implementation are as follows:

  1. Have the User and Role mapped under RoleMappings (image attached below)
  2. Have the ACLs setup in the models as per requirements

RoleMappings containing principalId as userId, principleType as RoleMapping.USER ('User')

The way loopback lets you handle the ACLs is quite sleek. I personally liked it when I got a hang of it.


Published by HackerNoon on 2017/03/15