Role-based Access to Routes in AdonisJS

AdonisJS provides a standard way to define a middleware and enable access to routes based on defined validation rules. This middleware is leveraged to allow role-based access to routes.

Your start | routes.js file will have something akin to below -

const Route = use("Route");

Route.get("/", () => {
  return { greeting: "Hello world!" };
});

First, we will group routes for the different roles and introduce the middleware.

// start | Routes.js
Route.group(() => {
  Route.post("/user-register", "UserController.register");
  Route.post("/user-login", "UserController.login");
});

Route.group(() => {
  Route.get("/todo", "TodoController.index");
  Route.post("/todo", "TodoController.create");
}).middleware("auth");

Route.group(() => {
  Route.delete("/todo", "TodoController.delete");
}).middleware(["auth", "admin"]);
  • register and login methods are available to unauthenticated and authenticated users
  • To do create and index are available only to authenticated users. auth is provided by AdonisJS
  • Deleting to do is allowed only for admin

Now, we write the actual middleware for admin.

Create a admin.js file in app| Middleware folder under root. Introduce the following code -

"use strict";

const InvalidAccessException = use("App/Exceptions/InvalidAccessException");

class Admin {
  async handle({ request, auth }, next) {
    const user = await auth.getUser();

    if (!user.role_cd || user.role_cd != "admin")
      throw new InvalidAccessException();

    await next();
  }
}

module.exports = Admin;

What happens when a user tries to access the delete route -

  • Adonis executes the auth and admin middleware
  • auth passes ok if user is authenticated
  • admin checks if the user.role_cd, a custom field, has the value ‘admin’. If this does not check out, an exception is thrown
  • InvalidAccessException is a custom exception that returns a 404 with a custom message (see [custom exceptions in Adonis)(/custom-exceptions-in-adonisjs/)

In a previous post we had a short discussion on implementing access rules in Adonis based on roles. Should you implement that vs. implementing the above in routes?

Well - it depends.

  • If the entire route is cordoned off to roles, you have a cleaner approach using role-based validation at the route level.
  • For everything else, let your controller take the lead for role-based authentication

In the real world, you would want to implement a separate service for role-based auth. This service can be called by your route middleware, or your controllers depending on your use case.

comments powered by Disqus