Authenticating Requests

By far and away the main thing you need to takeaway from this documentation of Auth Core is how to properly authenticate requests on the server side, as that is the main way that you use Auth Core through Group Control. It is important that every time you make a network requests that can be called through a router that you ensure that it is properly authenticated, otherwise, it is able to be protected from someone directly calling the API to do something that they shouldn't have permissions to do. There are three main ways you can authenticate a specific network request: the auth function, the check function, and the user isAuthenticated function. This assumes that your Controller properly extends Group Control's AuthController, which you can find described here.

Auth Function

The main way you will do authentication in each network request is by having an $this->auth() function call at the beginning of every network request. What the auth function does is it will call the session request to ensure you are logged in, then check against the permissions you pass in, and throw a 403 error if you do not have the proper permissions. The reason this is superior to other methods is that all this is done for you. There are times, however, when you will need to do something different depending upon what level of permissions the current user has, and those are the cases you use the functions described below. But for most cases, auth will be sufficient for your purposes. There are four ways to use auth, and those are: allowing a function to be completely public, they must be authenticated (but do not need any roles in the app), they must be authenticate with any roles in the app, and finally, they must be authenticated with specific roles in the app. We will speak about each of these cases individually. To know which level of authentication each network request requires, especially BREAD, is something you will need to plan and strategize based on the needs of your specific app.

Not Authenticated - Public Route

You are able to allow a route to be public based and not requre the user to be logged in at all to access it through the API, and this is by not calling the auth function at all. This is used on a few of the apps browse requests so that they can use the FW API to display data on the website (for example, Service Stats and Knowledgebase both have public browse requests). However, this should be used very sparingly, and unless there is a specific reason it is needed to be made public, then you should NOT use this method. In this method as well, it is usually best to have a way to differentiate between public and private data (such as a boolean on the table), and only display public data if not authenticated. If you use this method, you will need to use the other authentication methods described below so you can have the request work differently if it is actually an authenticated user. Knowledgebase and Service Stats are fine examples of this. Here is an example:

public function myRequest($object, $options) {
    // no auth function, so it is publicly accessible
    // rest of code below...
}

Authenticated - No Roles

There is an easy way to insure that the user is at least authenticated, without caring if they have any specific roles in the app, and this is by passing false into the auth function as its only parameter. This is used most often within Group Control requests so that users can access things like app data or department data without needing to have a specific role within the app (since most users do not have access to Group Control, but need to know what roles they have within the app). It is used in every app for the 404 page behind the scenes, so that if the user is logged in, but doesn't have access to the app it will load in the No Permissions page.

There may not be a lot of use case for you to enable this in your app's specific requests, but it is good to know that it exists in case the need does arise. You will need to use this method (together with the check function below) if you call any network requests on the application page (since it will cause an issue with the No Permissions page otherwise). Here is an example of this method:

public function myRequest($object, $options) {
    //authenticated, but no roles in app
    $this->auth(false);
    //rest of code here
}

Authenticated - Any Roles

Most often you will either use this authentication method or the next. Many network requests will not need to be restricted to any specific roles, but someone with the base role or any other role will be able to access them. In these cases, you will just use the auth function with no parameters. For example:

public function myRequest($object, $options) {
    // authenticated, with any role in the app
    $this->auth();
    // the rest of the code here...
}

Authenticated - Specific Roles

Often you will seek to restrict the operation of a specific route to specific roles. For example, the requests for objects set up in admin pages, often the browse and read requests will be accessible to any role, but add, edit, and delete will be admin only. There are many other examples in the apps of restricting for other reasons as well. In order to restrict a request to specific roles you need to pass in a permissions array, which works the same as our match functions on client side. How it works is that wrapping an item in one array will be an OR check, whereas wrapping an item in two arrays will be an AND check. This can be made as complicated or simple as you wish. If the query passes, then it will allow the network to load, but if it does not, then you will receive a no permissions error. Here are a few examples:

public function myRequest($object, $options) {
    // you should only have one auth function here at the beginning
    // several options are given to give you different examples of how to use auth
    $this->auth('admin'); // looking for only 'admin' role
    $this->auth(['stats', 'admin']); // either stats OR admin roles
    $this->auth([['admin', 'global-admin']]) // both admin AND global-admin roles
    $this->auth(['admin', ['stats', 'supervisor']]); // admin OR (stats AND supervisor)
    // the rest of the code here...
}

As you can see, you have a great level of flexibility when determining what roles are required, you just need to pass in the proper array. This will be invaluable to you as you are restricting certain functions to certain roles.

Advanced Usage - Throwing Specific Error

In advanced usage, you have the option of throwing a specific error, rather than the default StatusException of You are forbidden from doing this action, by passing in an Exception as the second parameter to the auth function (after the permissions array). This is hardly ever used, but you have the option to override the exception if you so desire. This would be how to do it:

public function myRequest($object, $options) {
    $this->auth('admin', \StatusException('Only admin are permitted to do this action', 403));
}

Check Function

The check function will return a Boolean as to whether the passed in roles array matches with the roles the current user has. It is useful for changing the function slightly based on role, after the function has already used one of the main four authentication methods listed above. The parameter is a match array, as was described for the auth function above. For example, maybe there is a specific column on the table that only admin are allowed to edit, this should be controlled with the following code:

// check for admin OR global-admin
if (!$this->check(['admin', 'global-admin'])) {
    unset($object['restrictedColumn']);
}

Other examples would be in a browse request changing slightly the query based on whether the user has a certain role level. Overall, it is a fairly simple function with many use cases, and is helpful to remember you have access to.

User isAuthenticated

The last authentication related item provided for you within controllers is the function isAuthenticated on the user object. As it sounds like, this will return a Boolean as to whether or not the user is authenticated within the app system or not. Obviously, if you have used any version of the auth function present, this will always be true (since it will have errored if not), but this is most useful when making a public route, when determining the difference of how the request will respond in a public vs. an authenticated context. For example:

public function myRequest($object, $options) {
    //no auth function - it is public
    if (!$this->user->isAuthenticated()) {
        // public version of request
    } else {
        // authenticated version of request
    }
}

Of course, there may be plenty of other uses for this command other than the one listed, and so it is just helpful in general to have knowledge of this ability.

Conclusion

Overall, regardless of how you authenticate requests using the Group Control Abilities, which use Auth Core, it is important THAT you have some form of authentication for every request. Becoming familiar with these various methods of authenticating will greatly aid you in being able to choose the right tool for the specific job you are seeking to do within each network request.