loopback-example-access-control
⚠️ This LoopBack 3 example project is no longer maintained. Please refer to LoopBack 4 Examples instead. ⚠️
$ git clone https://github.com/strongloop/loopback-example-access-control
$ cd loopback-example-access-control
$ npm install
$ node .
In this example, we create "Startkicker" (a basic Kickstarter-like
application) to demonstrate authentication and authorization mechanisms in
LoopBack. The application consists of four types of users:
guest
owner
team member
administrator
Each user type has permission to perform tasks based on their role and the
application's ACL (access control list) entries.
Prerequisites
Tutorials
- Getting started with LoopBack
- Other tutorials and examples
Knowledge
- EJS
- body-parser
- JSON
- LoopBack models
- LoopBack adding application logic
Procedure
Create the application
Application information
- Name:
loopback-example-access-control
- Directory to contain the project:
loopback-example-access-control
$ lb app loopback-example-access-control
... # follow the prompts
$ cd loopback-example-access-control
Add the models
Model information
- Name:
user
- Datasource:
db (memory)
- Base class:
User
- Expose via REST:
No
- Custom plural form: Leave blank
- Properties
- Name:
team
- Datasource:
db (memory)
- Base class:
PersistedModel
- Expose via REST:
No
- Custom plural form: Leave blank
- Properties
- Name:
project
- Datasource:
db (memory)
- Base class:
PersistedModel
- Expose via REST:
Yes
- Custom plural form: Leave blank
- Properties
No properties are required for the user model because we inherit them from
the built-in User model by specifying it as the base class.
$ lb model user
... # follow the prompts, repeat for `team` and `project`
Define the remote methods
Define three remote methods in project.js:
listProjects
donate
withdraw
Create the model relations
Model relation information
user
- has many
project
- Property name for the relation:
projects
- Custom foreign key:
ownerId
- Require a through model: No
team
- Property name for the relation:
teams
- Custom foreign key:
ownerId
- Require a through model: No
team
- has many
user
- Property name for the relation:
members
- Custom foreign key:
memberId
- Require a through model: No
project
- belongs to
user
- Property name for the relation:
user
- Custom foreign key:
ownerId
Add model instances
Create a boot script named sample-models.js.
This script does the following:
- Creates 3 users (
John, Jane, and
Bob)
- Creates project 1, sets
John as the owner, and adds John and Jane as team
members
- Creates project 2, sets
Jane as the owner and solo team
member
- Creates a role named
admin and adds a role mapping to make Bob an
admin
Configure server-side views
LoopBack comes preconfigured with EJS out-of-box. This means we can use
server-side templating by simply setting the proper view engine and a
directory to store the views.
Create a views directory to store server-side templates.
$ mkdir server/views
Create index.ejs in the views directory.
Configure server.js to use server-side
templating. Remember to import the path package.
Add routes
Create routes.js. This script does the following:
- Sets the
GET / route to render index.ejs
- Sets the
GET /projects route to render projects.ejs
- Sets the
POST /projects route to to render projects.ejs when credentials are valid and renders index.ejs when credentials are invalid
- Sets the
GET /logout route to log the user out
When you log in sucessfully, projects.html is rendered with the authenticated user's access token embedded into each link.
Create the views
Create the views directory to store views.
In this directory, create index.ejs and projects.ejs.
Create a role resolver
Create role-resolver.js.
This file checks if the context relates to the project model and if the
request maps to a user. If these two requirements are not met, the request is
denied. Otherwise, we check to see if the user is a team member and process
the request accordingly.
Create ACL entries
ACLs are used to restrict access to application REST endpoints.
ACL information
- Deny access to all project REST endpoints
- Select the model to apply the ACL entry to:
(all existing models)
- 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
- Allow unrestricted access to
GET /api/projects/listProjects
- Select the model to apply the ACL entry to:
project
- Select the ACL scope:
A single method
- Enter the method name:
listProjects
- Select the role:
All users
- Select the permission to apply:
Explicitly grant access
- Only allow admin unrestricted access to
GET /api/projects
- Select the model to apply the ACL entry to:
project
- Select the ACL scope:
A single method
- Enter the method name:
find
- Select the role:
other
- Enter the role name:
admin
- Select the permission to apply:
Explicitly grant access
- Only allow team members access to
GET /api/projects/:id
- Select the model to apply the ACL entry to:
project
- Select the ACL scope:
A single method
- Enter the method name:
findById
- Select the role:
other
- Enter the role name:
teamMember
- Select the permission to apply:
Explicitly grant access
- Allow authenticated users to access
POST /api/projects/donate
- Select the model to apply the ACL entry to:
project
- Select the ACL scope:
A single method
- Enter the method name:
donate
- Select the role:
Any authenticated user
- Select the permission to apply:
Explicitly grant access
- Allow owners access to
POST /api/projects/withdraw
- Select the model to apply the ACL entry to:
project
- Select the ACL scope:
A single method
- Enter the method name:
withdraw
- Select the role:
The user owning the object
- Select the permission to apply:
Explicitly grant access
$ lb acl
# follow the prompts, repeat for each ACL listed above
Try the application
Start the server (node .) and open localhost:3000 in your browser to view the app. You will see logins and explanations related to each user type we created:
- Guest
Guest
- Role = $everyone, $unauthenticated
- Has access to the "List projects" function, but none of the others
- John
Project owner
- Role = $everyone, $authenticated, teamMember, $owner
- Can access all functions except "View all projects"
- Jane
Project team member
- Role = $everyone, $authenticated, teamMember
- Can access all functions except "View all projects" and "Withdraw"
- Bob
Administrator
- Role = $everyone, $authenticated, admin
- Can access all functions except "Withdraw"
More LoopBack examples