$ 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.
- Getting started with LoopBack
- Tutorial series - step 1
- Tutorial series - step 2
- Tutorial series - step 3
- Name:
loopback-example-access-control
- Directory to contain the project:
loopback-example-access-control
$ slc loopback loopback-example-access-control
... # follow the prompts
$ cd loopback-example-access-control
- Name:
user
- Datasource:
db (memory)
- Base class:
User
- Expose via REST:
No
- Custom plural form: Leave blank
- Properties
- None
- Datasource:
- Name:
team
- Datasource:
db (memory)
- Base class:
PersistedModel
- Expose via REST:
No
- Custom plural form: Leave blank
- Properties
ownerId
- Number
- Not required
memberId
- Number
- Required
- Datasource:
- Name:
project
- Datasource:
db (memory)
- Base class:
PersistedModel
- Expose via REST:
Yes
- Custom plural form: Leave blank
- Properties
name
- String
- Not required
balance
- Number
- Not required
- Datasource:
No properties are required for the
user
model because we inherit them from the built-inUser
model by specifying it as the base class.
$ slc loopback:model user
... # follow the prompts, repeat for `team` and `project`
Define three remote methods in project.js
:
user
- has many
project
- Property name for the relation:
projects
- Custom foreign key:
ownerId
- Require a through model: No
- Property name for the relation:
team
- Property name for the relation:
teams
- Custom foreign key:
ownerId
- Require a through model: No
- Property name for the relation:
- has many
team
- has many
user
- Property name for the relation:
members
- Custom foreign key:
memberId
- Require a through model: No
- Property name for the relation:
- has many
project
- belongs to
user
- Property name for the relation:
user
- Custom foreign key:
ownerId
- Property name for the relation:
- belongs to
Create a boot script named sample-models.js
.
This script does the following:
- Creates 3 users (
John
,Jane
, andBob
) - Creates project 1, sets
John
as the owner, and addsJohn
andJane
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 makeBob
anadmin
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.
Create routes.js
. This script does the following:
- Sets the
GET /
route to renderindex.ejs
- Sets the
GET /projects
route to renderprojects.ejs
- Sets the
POST /projects
route to to renderprojects.ejs
when credentials are valid and rendersindex.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
directory to store views.
In this directory, create index.ejs
and projects.ejs
.
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.
ACLs are used to restrict access to application REST endpoints.
- 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
- Select the model to apply the ACL entry to:
- 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
- Select the model to apply the ACL entry to:
- 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
- Select the model to apply the ACL entry to:
- 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
- Select the model to apply the ACL entry to:
- 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
- Select the model to apply the ACL entry to:
- 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
- Select the model to apply the ACL entry to:
$ slc loopback:acl
# follow the prompts, repeat for each ACL listed above
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
Administator
- Role = $everyone, $authenticated, admin
- Can access all functions except "Withdraw"