Configure ACL’s to protect the LoopBack API

Bram Borggreve
InstructorBram Borggreve

Share this video with your friends

Send Tweet
Published 5 years ago
Updated 3 years ago

In this lesson we will learn how to protect our API using ACL’s.

ACL stands for Access Control List and it's function is to control permissions of resources in the API. It does this by keeping a mapping between an API resource and a principal. An API resource as an API endpoint like a remote method or a whole model. A principal in LoopBack are users or applications that can be grouped in a role.

In order to get the API production ready we will protect a selection of our REST endpoints with ACL’s. We will look at how we can obtain an access token and how we can use that in our requests.

Finally we will write some unit tests to make sure that the ACL does what we expect. We enhance our test setup by exporting request with is provided by the supertest library.

In our tests we use request to verify that our endpoints return the correct HTTP status code.

[00:00] Inside our LoopBack project, we run LBACL. This will prompt us for a model name. We choose products.

[00:06] The generator asks for the scope. We choose all methods and properties. For access type, we select all. For the role, we select any unauthenticated user. For the permission, we explicitly deny access.

[00:20] Now, if we look in our model definition, we see that we have a new object in the ACLs array which describes what we just created. Let's try this out in the API Explorer.

[00:29] We start our server by running npm run dev, and open the API Explorer in the browser. Where we go to the GetProducts endpoints and we try it out, we see that we get an error message saying authorization required.

[00:41] What we actually want to do is only allow the GetProducts endpoints, but disallow any other operations. That way, unauthenticated users cannot modify any data in their API, but can list it.

[00:53] We hop over to our terminal and run LBACL a second time. We select product, single method, enter the name, find, select any unauthenticated user, and explicitly grant access.

[01:07] In our product definition, we see that a new ACL rule got added to the ACLs array. When we start our server again and we try the same endpoint, we see that we can now list our products.

[01:17] Other endpoints like delete/products still return authorization required. Because we want to have the same ACLs for the category model, we just copy the content of the ACLs array from product.json, and paste it in the ACLs array in category.json.

[01:33] Instead of verifying through the API Explorer, let's add some tests to make sure our permissions are set as expected. We create the file ACL.test.js, and start by requiring app, expect, and request from common.

[01:46] We currently don't export requests. Let's open our common.js, require SuperTest, create a constant called request which loads our app into SuperTest, and export request.

[01:59] Because we did not install SuperTest yet, we go over to our terminal and install SuperTest as a dev dependency. Inside our ACL test, we create a new describe block for the ACL. Let's begin by testing the category model.

[02:12] In the first test, we want to list the products and expect to have an HB200 response. In the next three tests for creating, updating, and deleting a category, we owe expect an HB401 authentication required response. When we run our tests, we see that they pass.

[02:30] We add the same test for the product model. List is allowed. Create, update, and delete are denied. For the product model, we have an extra test for the buy methods.

[02:41] Where we run our test, we see that we have one failing test. The buy method expected to be allowed, but was denied. We can fix that by opening product.json and change the string find into an array with find and buy. When we run our tests again, we see that they now all pass.

~ 5 years ago

Hello, So far I have really enjoyed your course. I am having an issue with the buy now though. I did fix the 401 by adding the buy property to the ACL but now I am getting a 400 "Bad Request" with the following code:

<pre> it('should return 200 when buying a Product', function() { return app.models.Product.create({ name: 'Test', price: 100 }) .then(res => request .post(`/api/Products/${}/buy`) .send({ quantity: 100 }) .expect(200)); }); </pre>

What am I missing?

Thanks again for your great courses.

~ 5 years ago

Never mind, if I could spell it would help! I saw the problem, it was the mis-spelling of quantity in the product.js file.

Martin Christov
Martin Christov
~ 4 years ago

Hey man, You say in the description "We will look at how we can obtain an access token and how we can use that in our requests." But you never did :/

PS: Nevermind. I should have played the next video first :)