Implementing client-side authorization is one of the toughest topics for frontend developers. Not just because it's complicated, but also it takes time to build it, especially for Business SaaS applications.
- Wide range of best practices for different tech stacks (Frameworks, languages etc.)
- Different access control needs of your users.
- Flexibility and maintenance.
Although there are many ways to implement authorization & access control, I’ll share an effective approach to implement RBAC in VueJs applications. To keep this article simple and easy to understand, we’re going through a demo project generated with the Vue CLI.
Creating Vue demo project:
From your Terminal or Command Prompt, execute the following command to create a new project:
Firstly, we need to clear our application in order to start fresh. So after the Vue project is generated your folder structure should look like following unless you didn’t choose features manually while creating your app.
Restructuring the project:
Just remove folders, assets, and components. Open up a folder called views and create;
- Home.vue as a public page
- ContactDetails.vue file as our protected page
- Unauthorized.vue file for redirecting on forbidden access attempts
After these operations, we need to define our application routers by creating a new folder called router, then add index.js within it to create routes.
Firstly we need to install “vue-router” with following command:
npm install vue-router@3
Note: Since we are using default Vue 2.0 project, I added the vue router version 3. If you're using Vue 3.0 you can install latest version of it. You can find the latest changes and migrating from Vue 2 informations on this page --> router.vuejs.org/guide/migration/
After “vue-router” package installed, we will create router/index.js as follows:
To keep things simple and clear, I just define the minimum required routes. As you can see I change the default mode to history mode in order to discard the ‘#/‘ situation.
Also, I add “authRequired” meta attribute to each route to understand which page is protected. If “authRequired” meta is ‘false’ we don’t need to check the authorization of the user, like on the home page.
After setting up the router, Let’s add it to main.js with the following code:
As a result of clearing and updating our demo project, our folder structure should look like below:
Creating User object with role and permissions:
In order to control access checks, we need logged-in users’ roles and permissions. In real-world applications, there are a couple of ways to get and set the users’ roles and permissions from your server API.
However since this is a demo app; I’ll create a sample user JSON, and use its roles and permissions in order to perform access checks.
Let's create user.json file inside our source folder, and add the following sample JSON data:
After adding user.json, we'll update our App.js file, lets make It a simple link page that behaves like a standard navigation bar with default styles as below:
To start our project let's execute npm serve (or yarn serve whichever you use). You should see a page similar to the below:
Access Control Using Permissions and Roles in Vue
In the previous steps, we reorganize our project and create a sample user JSON. Now we can implement access control in our frontend based on users’ roles and permissions.
Let's implement access control for both our routes and UI elements.
Access Control In Route Level
We’ll implement access control for our application’s routes by checking certain conditions before every route change, let’s create fake conditions for users to access the contact details page:
- Admin and super admin roles can directly access contact details.
- If the user is the contact itself, he/she can access their own details as expected.
- Manager role can access contact details only if the user has permissions “create-contact” and “update-contact”.
Users can access the contact details page if conditions hold true for them.
The vue-router package provides beforeEach() method which we use to perform our access checks. beforeEach() is a navigation guard responsible for protecting routes on navigation change, as you can tell by the name, it invokes before every route change.
So let’s import user.js in router/index.js file and add the beforeEach() method below our router instance as follows:
Access Control In UI Layers and Components
In the previous step, we cover the access checks at route level, The second common way is flagging components or UI layers.
Simply, we want to show/hide certain elements on our page depending on users’ permissions. For instance, we want to show certain components only to the users who met the conditions. Otherwise, we won’t show you those specific components.
We can use created property to implement access control logic to our components, also we need to set a condition to UI elements to perform hide/show actions. We can easily do that with v-if directive.
To see this component-level access check in action lets add a components folder and create CreateContact.vue file with the following code:
To see our create contact component in action we'll add it to Home Page as follows:
Why you probably need to outsource Access Control
You can use many different methods instead of this. For instance, if you want more dynamic approach, using computed property instead of created might be a good solution for you.
Apart from these, as you noticed we created fake scenario conditions and handle their access checks with if-else.
Adding everywhere this kind of heavy loaded if checks might not be an ideal case for a real-world application. Also, you should get / fetch every information that you check on “if” statement. In this demo app we just gave user.json sample object, and didn’t care that too much.
I try to keep things simple for demonstration purposes. But developing an RBAC mechanism on scale up application is much tougher than it should be.
If you have any questions or doubts, feel free to ask them. Also you can find the source code of the application here: github.com/EgeAytin/vue-rbac-demo
For more content like this, join our newsletter. Get best practices on Authentication, Authorization and Subscriptions to build ultimate B2B SaaS apps.