Authentication is the mechanism used by software systems to securely identify their users.
Authorization is the mechanism that provides what level of access a certain system user should have.
Currently, many systems are using username and password pairs in order to authenticate their users and this is the case for our package also.
WiseLoop PHP REST Services offers a very nice out-of-the-box implementation of these concepts, while also leaving the flexibility of implementing own security mechanisms.
In order to add security support for an API, one should define an auth handler that will describe the authentication & authorization mechanisms for the API:
class myAuthHandler extends wlAuthHandler { public function authenticate($authData){ //authenticate $authData and array or an object that should contain the username and password to be authenticated } public function isAuthorized($request) { //authorize the $request } }
An auth handler should be derived from wlAuthHandler and should overwrite wlAuthHandler::authenticate and wlAuthHandler::isAuthorized methods.
Method wlAuthHandler::isAuthorized should return bool and takes as parameter the current request; see wlRestRequest for more information.
To enable authentication, the auth handler must be instantiated and used inside wlRestControllerAuth that should be registered in within our service:
$authHandler = new myAuthHandler(); $service->registerController(new wlRestControllerAuth($authHandler));
To enable authorization, the auth handler must be instantiated and used inside a trigger registered in our service at request time:
$service->registerTrigger(new wlRestTriggerAuth($authHandler), wlRestTrigger::ON_REQUEST_EVENT);
Now, each incoming request will be validated by the handler wlAuthHandler::isAuthorized method.
For convenience, the package contains a few built-in and ready to be used auth handlers that provides authentication for username / password credentials provided by different means:
Please check the corresponding documentation of each handler for more details.
To enable authorization also, it's a good idea to create a new auth handler by inheriting the built-in one and specify own authorization logic by overwriting the wlAuthHandler::isAuthorized method.
The most common and the recommended way of securing your API is by using a trigger registered at on-request time.
Let's suppose we have a local MySQL database called my_database and the table where the credentials are stored is called users.
To access the database we will user the following credentials: 'root' for the username and 'secret' for the password.
The users table consists of the following fields:
We want to build an API that will authenticate against the users table and authorize some CRUD operation depending on is_admin and is_editor fields.
class myAuthHandler extends wlAuthHandlerPdoMySql { public function isAuthorized($request) { //here, the $authData will be an associative array with the fields taken from the database table: username, is_admin, is_editor (without password) $authData = $this->get(); $isAdmin = $authData['is_admin']; $isEditor = $authData['is_editor']; $fullName = $authData['fullName']; //implement own authorization logic ... $controller = $request->getControllerName(); if($controller == 'post' && ($isAdmin || $isEditor)) { return true; }elseif($controller == 'user' && $isAdmin) { return true; } return parent::isAuthorized($request); } }
In this sample the authorization logic is dependent on the controller name of the request and it is written directly inside the isAuthorized method. This logic can be more complex dependent on other request parameters such as method or payload and for a cleaner code it can be written in external helpers or call external methods. It is really up to you how this logic should be implemented as PHP Rest Services offers this authorization wrapper around the requests.
After registering the handler with the service API you want to build through the wlRestControllerAuth controller and enable authorization through triggers, the framework will take care of everything:
//create the service object $service = new wlRestService(); // ... register API controllers, output handlers, triggers etc. //instantiate the auth handler $authHandler = new myAuthHandler('localhost', 'my_database', 'root', 'secret', 'users', 'username', 'password', true); $service->registerController(new wlRestControllerAuth($authHandler)); $service->registerTrigger(new wlRestTriggerAuth($authHandler), wlRestTrigger::ON_REQUEST_EVENT); //run the service $service->run();
Please check the Creating REST Services for more information regarding the creation of a basic API. The commercial package includes a fully functional demo that can serve as a very good sample for implementing security for you API.
After registering the auth handler using the wlRestControllerAuth controller, our API will be enriched with a few more routes dealing with the authentication mechanism:
Please check the full included sample to see an actual secured API implementation.
Of course, you are free to extend the basic wlRestControllerAuth, change the default 'auth' name, add new routes (maybe for user management) and use your controller for authentication mechanism.
Although it is the recommended way, one can find unhandy implementing the full authorization mechanism in a single method wlAuthHandler::isAuthorized as described above.
Fortunately, PHP Rest Services provides also another way of authorization mechanism specified at controller route level:
class someController extends wlRestController { public function getDefaultName() { return 'some'; } protected function nameGetAllowed() { $params = $this->actionParams; // ... any logic here return true; //false } protected function nameGet() { return array('my-name' => 'John'); } }
Basically, this is a convention that of you want to validate a certain route, you need to suffix it's corresponding method with 'Allowed'. The suffixed 'Allowed' method will be evaluated before the actual route method that will be executed only if the evaluation result is true. If false, the API call will return 403 Forbidden status.
Because the route validation take place at the method level, if you opt for this authorization method, there is no need to register any trigger like described in the previous chapter.
Of course, you can combine the two authorization methods to suit your needs.
Building a RESTful web service for your PHP web application has never been so easy!
WiseLoop PHP REST Services is a powerful API framework that allows easy development of any kind of API through RESTful web services.