Authenticate users based on both user role, and requested operation I have a function that checks if a user can perform an operation based on access to a specific URL.

The function parameters are the requested URL: url, and user level: lv. The conf object has stored access levels for comparison with the users access level. 

function isAuthenticated(url, lv){
    let conf = config.getConfig();

    // Role Editor
    if((url === "/RoleEditor" || url === "/SaveRoles") &amp;&amp; lv &gt; conf.roleEditor)
        return true;
    // Queue
    if(url === "/WriteQueueData" &amp;&amp; lv &gt; conf.queuedata)
        return true;
    // Listener
    if((url === "/startListener" || url === "/stopListener" || url === "restartListener" || url === "/ListenerConfig" || url === "/SaveListenerConfig") &amp;&amp; lv &gt; conf.listener)
        return true;
    // Client details
    if(url === "/ClientInfo" &amp;&amp; lv &gt; conf.clientDetails)
        return true;
    // User information
    if(url === "/UserManagement" &amp;&amp; lv &gt; conf.userOverview)
        return true;
    // User Edit
    if((url === "/EditUser" || url === "/EditUserToDb") &amp;&amp; lv &gt; conf.userEdit)
        return true;

    //
    // Another 6 of this comparisons
    //
    return false;
}


This seems inefficient. For example, if the url is "/RoleEditor" but the power level is too low, all other comparisons are still being made. This could be fixed by changing to this:

if((url === "/RoleEditor" || url === "/SaveRoles"))
    if(lv &gt; conf.roleEditor)
        return true;
    else
        return false;


But that feels even worse (more redundant).

Is there a better way to do this?
If return true, else return false

if(lv &gt; conf.roleEditor)
    return true;
else
    return false;


Before we delve into the contextual considerations, an if that returns true or false is always a redundant if. This can at all times be refactored to:

return lv &gt; conf.roleEditor;


Performance


  I see that, if the url is "/RoleEditor" but the power level is too low, all other comparisons will be made. A fix for this would be changing all to this:


The first question is always "does this performance need to be optimized?" As these are simple value comparisons, the performance cost is likely negligible. Assuming this method isn't being called many thousands of times in a given page load.

When performance cost is negligible, favor readability over (irrelevant) optimizations. In that regard, you're free to not avoid the additional checks if it makes the code more readable and doesn't meaningfully impact performance.

That being said, the code can be improved here, which I will get to. The main takeaway here is that you are not forced to optimize it the way you currently wanted to if there is no proven performance issue.

Authentication vs authorization

As others have already remarked, you're dealing with authorization here, not authentication.


Authentication = Who is this? (it's Bob)
Authorization = Can Bob delete users? (yes)


Secure authorization

You are showing a javascript method. Presumably, this runs in the client's browser. By putting the logic in the browser, your users are able to find it and alter it if they so choose. This is a bad idea for security concerns.

It's not necessarily wrong to perform these checks client-side (e.g. for a fast response and thus good user experience) if they are also backed by server-side security checks (to ensure that users fiddling with the authorization logic client-side are unable to perform actions server-side).

Optimizing the algorithm

With all these sidenotes out of the way, we move on to the actual issue you were asking about, optimizing the ifs. Reading the code, there is a general pattern to be spotted:

if(url == "MyString" &amp;&amp; lv &gt; conf.MyStringMinimumLevel)


Sometimes there is more than one allowed string, so we'll account for that, but the repeating pattern is otherwise always the same. I'm going to refer to these two values as "names" and "levels" in the rest of the answer for brevity's sake.

This immediately opens the door to abstraction by mapping these names and levels. In fact, you've already sort of done this with all your conf.roleEditor, conf.queuedata, ... values. You just haven't done it reusably, which is forcing you to manually write all your if checks. If you write it reusable, you can reduce this to a very simple process:


Fetch the level based on the url name
Check if the given user level is greater than the fetched level




var mappings = 
{
    {
        "level" : 1
        "names" : [ "RoleEditor", "SaveRoles" ]
    },
    {
        "level" : 2
        "names" : [ "WriteQueueData" ]
    }
};

function isAuthorized(url, lv) {

    var mapping = mappings.find(m =&gt; m.names.includes(url.trim('/'));

    return mapping !== undefined
           &amp;&amp; lv &gt; mapping.level;
}


To explain:


.find() gives us the first item which conforms to the selection logic (or undefined if no such item exists). 
The selection logic (.includes()) checks if a mapping contains a name that matches the url parameter.
By using url.trim('/'), you omit the first and last character (the /) from the URL when it is a / (but will leave any other characters). This just makes it easier for use to not have to constantly put the / in the mapping names.
The !== undefined check ensures that we return false if no mapping exists for the current URL. Your intended behavior may be different here - adjust it as you see fit.


You'll probably want to store this mapping in your conf object, but I'll leave the finer points up to you. This is just a basic example of how you can reduce the method.

Edit: Sidenote

If the conf object should not be altered (for whatever reason), you can work around this by indirectly using the values in the mappings:

var mappings = 
{
    {
        "level" : conf.roleEditor,
        "names" : [ "RoleEditor", "SaveRoles" ]
    },
    {
        "level" : conf.queuedata,
        "names" : [ "WriteQueueData" ]
    }
};

// The function is unchanged


This is less ideal (it's better to just change the conf object) but if you can't change it, you can at least still work around it.