Yii 1.1: How-To: Create Token Authenticated Web Services

17 followers

This article is about implementing authentication to Yii based web services.

In this article we shall cover authentication for POST requests For other request code can be modified easily.

Useful Tools

To test these web services you can use the [Firefox Poster Addon] (https://addons.mozilla.org/en-US/firefox/addon/poster/).

Create a web services controller

Create a new Site Controller

class SiteController extends Controller {
 
    public $layout = false;
 
    /**
     * @return array action filters
     */
    public function filters() {
        return array(
            'postOnly + heartbeat',
        );
    }
 
    /**
     * This is the action to handle external exceptions.
     */
    public function actionError() {
        if ($error = Yii::app()->errorHandler->error) {
 
 
            $filterErrorArray = array(
                'code' => $error['code'],
                'errorCode' => $error['errorCode'],
                'message' => $error['message'],
            );
 
            if (Yii::app()->params['apidebug']) {
                $filterErrorArray['type'] = $error['type'];
                $filterErrorArray['file'] = $error['file'];
                $filterErrorArray['line'] = $error['line'];
            }
 
 
            echo CJSON::encode($filterErrorArray);
        }
    }
 
    public function actionHeartBeat() {
        $code = '00';
        $message = 'Heartbeat Successful';
        echo CJSON::encode(array(
            'code' => $code,
            'message' => $message
        ));
    }
 
}

Actions

Handling errors

public function actionError() {
     .....
}

This function will show error information in JSON output. Put a flag in params to manage what data should be shown to responses in different modes.

Web Service test function

public function actionHeartBeat() {
   ......
 
}

Test function to check if web service is working or not.

Authentication

I have here used a bit tricky method for authentication. Yii core have functionality to handle CSRF protection. In web services all the requests from another server so we do't need this functionality. We can override this to authenticate clients requests.

Override HTTPRequest

Create new file HttpRequest.php in components

<?php
 
/*
 * This file contain the code to  use custom Http Request instead of Yii's Automatic request
 */
 
class HttpRequest extends CHttpRequest {
 
    public $tokenName = 'password';
    public $appName = 'username';
 
    public function authenticateApp($params) {
 
        $attributes = array(
            'token' => trim($params['token']),
            'name' => trim($params['name']),
            'status' => 1
        );
 
 
        $tokemExists = App::model()->findByAttributes($attributes);
 
        if ($tokemExists) {
            return true;
        } else {
            return false;
        }
    }
 
    /**
     * Overrided it to use apptoken.
     */
    public function validateCsrfToken($event) {
        if ($this->getIsPostRequest()) {
 
 
            if (isset($_POST[$this->tokenName]) && isset($_POST[$this->appName])) {
 
                $params = array(
                    'token' => $_POST[$this->tokenName],
                    'name' => $_POST[$this->appName]
                );
 
                $valid = $this->authenticateApp($params);
            } else {
                $valid = false;
            }
 
            if (!$valid) {
                if (isset(Yii::app()->user->id)) {
                    Yii::app()->user->logout();
                }
 
                throw new CHttpException(400, Yii::t('yii', 'Authentication failed.'));
            }
        }
    }
 
}
 
?>

Whenever there is post request it will trigger the authentication function for the request.

Add config in main.php

To enable this token add following to components.

'components' => array(
  ........
                'request' => array(
                    'class' => 'application.components.HttpRequest',
                    'enableCsrfValidation' => true,
                ),
.........
)

Table to store authentication data

Create a new table to store web service authentication data.

CREATE TABLE IF NOT EXISTS `tbl_app` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(200) DEFAULT NULL,
  `token` varchar(500) DEFAULT NULL,
  `status` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
 
 
INSERT INTO `tbl_app` (`id`, `name`, `token`, `status`) VALUES
(1, 'test', 'xyz', 1);

Generate model using Gii for this table.

Test WebService

Below are the steps to test Webservices by Poster Firefox add on.

  1. Open poster from tools (ctrl+alt+P)
  2. Provide url for webservice i.e http://www.example.com/index.php?r=site/heartbeat
  3. Add parameter username as "test" and password as "xyz"
  4. Click on content to send and choose content options as "Body from Parameters"
  5. Post the request.

Note:- We are using this authentication services for our web services. It may not be the best practice to authenticate web services. Your comments are welcomed.

Total 1 comment

#16052 report it
le_top at 2014/01/14 06:15pm
Alternate method also documented

Hi I have documented my method (not as well documented, but different method): http://www.yiiframework.com/wiki/607/how-to-use-token-based-authentication/

Leave a comment

Please to leave your comment.

Write new article