javascripttypescriptadonis.jslucid

Is it safe to authorize user models using `instanceof` in JavaScript / TypeScript?


Let's say I have 3 models: Admin, User, Product (I'm using model classes)

Only an admin can ADD, UPDATE, DELETE a product and users can only GET products, so I have registered an ACL middleware for corresponding routes.

Now in my ACL middleware, I want to authorize users, and if they are ADMIN, I will call next() method, otherwise, I'm going to reject the request with a 401.

I found it easy to do the check using JavaScript's instanceof operator:

const user = await auth.authenticate()

if (user instanceof Admin) {
  await next()
} else {
  throw UnAuthorizedUserException
}

await auth.authenticate() returns the current user sending the request, be it a user or an admin

However, I'm not sure if this is the safest way to distinguish b/w admins and users.

Now my question is, am I doing it right? Which approach is better than what I'm doing?

Note (if it helps): I'm using Adonis.js v5, TypeScript and Lucid models


Solution

  • Yes you can do this. You will need to be careful about inheritance patterns if you use this approach. You may want to consider adding a role property to the user object and using that for the check.

    example using a role prop.

    if (user.role === 'ADMIN') {
      ...
    }
    

    example of instanceof backfiring on you

    class User {}
    class Admin extends User {}
    
    const user = new User;
    const admin = new Admin;
    
    console.log(user instanceof User); // true
    console.log(user instanceof Admin); // false
    console.log(admin instanceof User); // true **watch out for this**
    console.log(admin instanceof Admin); // true