#loopback-example-access-control
$ 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
- Tutorial series - step 1
- Tutorial series - step 2
- Tutorial series - step 3
###Knowledge
##Procedure
###Create the application
####Application information
- 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
###Add the models
####Model information
- 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 the remote methods
Define three remote methods in project.js
:
###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
- 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
###Add model instances
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
###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
Add server-side templating configurations to server.js
.
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 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
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
- 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
###Try the application
Start the server (node .
) and open [localhost:3000
][localhost] 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"