Tag Archives: php

Securing your PHP REST API with OAuth

Problem:

There are many considerations to make when building and securing a public-facing API, but I wanted to look at one issue in particular: Making sure that only authenticated clients can access it.

The aim of this tutorial is to create a flow where a client only needs to make one request to the server to get back a response. In this simple application flow, we can avoid the added complexity of managing request and/or access tokens:

  1. Client sends a request for data along with their authentication details
  2. Server sends data back to the authenticated client

This flow will be familiar if you have used Amazon Web Services (AWS) before, as they use a similar “signed-message” system.

Solution:

Use a simple version of the OAuth 1.0a standard which is known as “2-legged” authentication. In this system, no access tokens are used. Authentication is performed using a public and private key system. These public and private keys are known by the client (consumer) and the server (provider).

  • The private key (the secret) is NEVER passed over the wire
  • The provider uses the private key within a hash-based message authentication code (HMAC) to generate a signature
  • The consumer uses its own copy of the private key to verify the signature is authentic
  • You should use always SSL/TLS to encrypt traffic between the consumer and provider

My solution uses PHP OAuth library by Andy Smith (MIT licence) for the heavy lifting. I have made this library available as a Composer package which can be installed like this:

$ php composer.phar require glenscott/oauth

Here are two simple examples for the provider and consumer sides:

Provider side

In this example, the list of valid consumer keys and secrets are hardcoded, but you probably want to store these in a DB somewhere. The provider will return "true" if it is a valid authenticated request, or otherwise it will spit out and error message "Exception: ...".

File: provider.php

<?php

require_once dirname(__FILE__) . '/vendor/autoload.php';

use GlenScott\OAuth;
use GlenScott\OAuthProvider;

require_once 'datastore.php';

$server = new OAuth\Server(new OAuthProvider\ExampleDataStore());
$server->add_signature_method(new OAuth\SignatureMethod_HMAC_SHA1());
 
$request = OAuth\Request::from_request();
 
try {
    if ( $server->verify_request($request) ) {
        echo json_encode(true);
    }
}
catch (Exception $e) {
    echo json_encode("Exception: " . $e->getMessage());
}

file: datastore.php

<?php

namespace GlenScott\OAuthProvider;

require_once dirname(__FILE__) . '/vendor/autoload.php';

use GlenScott\OAuth;

class ExampleDataStore extends OAuth\DataStore {
    function lookup_consumer($consumer_key) {
        $consumer_secrets = array( 'thisisakey'     => 'thisisasecret',
                                   'anotherkey'     => 'f3ac5b093f3eab260520d8e3049561e6',
                                 );
 
        if ( isset($consumer_secrets[$consumer_key])) {
            return new OAuth\Consumer($consumer_key, $consumer_secrets[$consumer_key], NULL);
        }
        else {
            return false;
        }
    }
 
    function lookup_token($consumer, $token_type, $token) {
        // we are not using tokens, so return empty token
        return new OAuth\Token("", "");
    }
 
    function lookup_nonce($consumer, $token, $nonce, $timestamp) {
        // @todo lookup nonce and make sure it hasn't been used before (perhaps in combination with timestamp?)
        return NULL;
    }
 
    function new_request_token($consumer, $callback = null) {
 
    }
 
    function new_access_token($token, $consumer, $verifier = null) {
 
    }
}

Consumer side

file: consumer.php

<?php

require_once dirname(__FILE__) . '/vendor/autoload.php';
 
use GlenScott\OAuth;

// this is sent with each request, and doesn't matter if it is public
$consumer_key = 'thisisakey';
 
// this should never be sent directly over the wire
$private_key  = 'thisisasecret';
 
// API endpoint -- note that in prodution, you _must_ use https rather than http
$url = 'http://localhost:8080/provider.php';
 
// the custom paramters you want to send to the endpoint
$params = array( 'foo' => 'bar',
                 'bar' => 'foo',
                 );
 
$consumer = new OAuth\Consumer($consumer_key, $private_key);
$request  = OAuth\Request::from_consumer_and_token($consumer, NULL, 'GET', $url, $params);
 
$sig = new OAuth\SignatureMethod_HMAC_SHA1();
 
$request->sign_request($sig, $consumer, null);
 
$opts = array(
    'http' => array(
        'header' => $request->to_header()
    )
);
 
$context = stream_context_create($opts);
 
$url = $url . '?' . http_build_query($params);
 
echo "Making request: " . $url . PHP_EOL;
echo "Authorization HTTP Header: " . $request->to_header() . PHP_EOL;
echo "Response: " . file_get_contents($url, false, $context) . PHP_EOL;

To run the above example, run the PHP development server using php -S localhost:8080 and run php consumer.php:

Making request: http://localhost:8080/provider.php?foo=bar&bar=foo
Authorization HTTP Header: Authorization: OAuth oauth_version="1.0",oauth_nonce="7620de430a896a5594fbf76e96f3b3d3",oauth_timestamp="1510494497",oauth_consumer_key="thisisakey",oauth_signature_method="HMAC-SHA1",oauth_signature="4V8Ft368ZBWxh5V10jv1AW%2FJwls%3D"
Response: true

Using the samples above should give you a head-start when creating your own authenticated API.

Any questions? Please use the comments section below!

Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn

Securing your CodeIgniter passwords with bcrypt

Safe

I’ve applied a small modification to the Portable PHP password hashing framework, so it can be easily used in CodeIgniter projects. An example of using it to authenticate users:

$this->load->library( 'PasswordHash' );

    $query = $this->db->query("
        SELECT
            `user_id`,`password` AS `hash`
        FROM
            `user`
        WHERE   
            `username` = ". $this->db->escape($username) ."
        LIMIT
            1
    ");

    // check to see whether username exists
    if ( $query->num_rows() == 1 ) {
        $row = $query->row();

        if ( $this->passwordhash->CheckPassword( $password, $row->hash ) ) {
            return $row->user_id;
        }
    }

To generate a hashed password:

    $this->load->library( 'PasswordHash' );

    $password = ( isset( $_POST['password'] ) ? $_POST['password'] : '' );

    if ( $password ) {
        $hash = $this->passwordhash->HashPassword( $password );

        if ( strlen( $hash ) < 20 ) {
            exit( "Failed to hash new password" );
        }
    }

For more details, please check out the repository on GitHub: github.com/glenscott/passwordhash-ci

Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn

Compiling PHP extensions using Xcode 4.3 and above

Prior to version 4.3 of Xcode, Apple bundled a load of command line tools with it that are used to compile native binaries, including PHP extensions. However, as of version 4.3, these tools are not bundled by default. Therefore, if you require these tools you need to take one of two actions:

1. If you already have Xcode 4.3 installed, go into the Components tab of the Download preferences panel and make sure Command Line Tools are selected

Xcode CLI tools installation

OR

2. Download and install the command line tools as an independent package from either;

a. Apple (requires Apple ID)
b. GitHub

Once you have the command line tools installed, you are able to compile native binaries.

If you found this post useful, it would be great if you could Like my Facebook page using the button in the sidebar. Thanks!

Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn

Refactoring a large PHP codebase – where do you start?

If you are finding a codebase less manageable than it should be, chances are that refactoring could help. But where can you start? I’ve found the following tools are good for focussing on the areas of code that require attention:

PHPMD – http://phpmd.org/

PHPMD (Mess Detector) scans your source code and computes various quality metrics such as cyclomatic and NPath complexity. These metrics can be used to assess which classes in your codebase need refactoring.

phpcpd – https://github.com/sebastianbergmann/phpcpd

phpcd (Copy Paste Detector) scans your source for code clones — identical fragments of code that are usually created by copying and pasting. Source code with high levels of clones may benefit from refactoring.

What are your favourite tools to help in your refactoring efforts?

Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn

Finding function dependencies in your PHP applications

wide web

A recent post on reddit/PHP asked an interesting question: how can you determine the extension requirements of your PHP application in a programmatic way? And could you add such a check to a continuous integration environment to validate dependencies?

I’ve come up with a relative simple solution, albeit with some caveats (see below). The process requires two distinct stages:

  1. Gather a list of extensions and functions from a PHP environment
  2. Scan PHP source code for function calls and flag up any that are not either a) available in the PHP environment or b) user defined.

I’ve posted some code to Github that demonstrates how this can be done. You can find the source code here: https://github.com/glenscott/php-dependencies.

For stage 1, you must determine the functions that are defined in your PHP environment. This is done by running get-env-functions.php either on the command line, or from within your document root. This will create a config file in the directory defined by CONFIG_PATH. This config file will be used by the second script, scan-dependencies.php.

scan-dependencies.php will scan through PHP source code defined by SOURCE_PATH and use the configuration file generated previously. After it finishes scanning, it will list all function calls made that are not defined in either PHP itself, or within the source directory.

Example Run

Getting details of your PHP environment

$ php get-env-functions.php 
Found 1743 total functions in 61 extensions available in PHP.

Scanning source code for dependencies

$ php scan-dependencies.php 
Found 3 function calls and 1 object instantiations in your script.
Function ps_setgray not defined.

In this example, the function ps_setgray was called in a script but not defined anywhere.

Caveats

  • Your source code and its dependencies must lie under one directory — included/required files outside this directory are not scanned
  • As it stands, only _function_ dependencies are found. This means that class dependencies are not checked.

Final thoughts

This is by no means a complete solution, but I hope it is of some use. Please feel free to comment, or suggest improvements.

Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn

Installing Alternative PHP Cache (APC) on Mac OS X Lion

The APC extension should be a straightforward PECL install, but sadly it does not work on Mac OS X Lion. Attempting to install will result in make errors similar to the following:

In file included from /private/tmp/APC/apc.c:44:
/usr/include/php/ext/pcre/php_pcre.h:29:18: error: pcre.h: No such file or directory
In file included from /private/tmp/APC/apc.c:44:
/usr/include/php/ext/pcre/php_pcre.h:37: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
/usr/include/php/ext/pcre/php_pcre.h:38: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
/usr/include/php/ext/pcre/php_pcre.h:44: error: expected specifier-qualifier-list before ‘pcre’
/private/tmp/APC/apc.c:393: error: expected specifier-qualifier-list before ‘pcre’
/private/tmp/APC/apc.c: In function ‘apc_regex_compile_array’:
/private/tmp/APC/apc.c:454: error: ‘apc_regex’ has no member named ‘preg’
/private/tmp/APC/apc.c:454: error: ‘apc_regex’ has no member named ‘preg’
/private/tmp/APC/apc.c:455: error: ‘apc_regex’ has no member named ‘nreg’
/private/tmp/APC/apc.c:455: error: ‘apc_regex’ has no member named ‘nreg’
/private/tmp/APC/apc.c: In function ‘apc_regex_match_array’:
/private/tmp/APC/apc.c:487: error: ‘apc_regex’ has no member named ‘preg’
/private/tmp/APC/apc.c:487: error: ‘apc_regex’ has no member named ‘preg’
/private/tmp/APC/apc.c:488: error: ‘apc_regex’ has no member named ‘nreg’
/private/tmp/APC/apc.c:488: error: ‘apc_regex’ has no member named ‘nreg’
make: *** [apc.lo] Error 1
ERROR: `make' failed

Thankfully, the solution is simple. To being with, make sure you have Xcode installed. If you have xCode 4.3 or above, make sure you have the command line tools installed.

APC requires PCRE libraries and header files to be available, so we can download and install these from source:

./configure
make
sudo make install

Next, we can install the APC extension using the normal PECL route:

sudo pecl install apc

Confirm that you have the following line in your php.ini file:

extension=apc.so

Restart Apache, if required:

sudo apachectl graceful

You should now have APC available, and you can confirm this by looking at your phpinfo output:

APC PHP info


Want advice on building better software? Join my mailing list…


Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn

Install mcrypt PHP extension on Mac OS X Lion

Important: This article was originally published in 2011, and I wouldn’t recommend you use mcrypt in your PHP project any more (reasons why). If you absolutely need it… then read on….

mcrypt php extension

If you have a need to install the mcrypt extension for PHP, for example if you need to use phpMyAdmin, Magento or Laravel, then these instructions are for you.

Thankfully, it is becoming simpler to install PHP extensions than with previous versions of OS X.

Xcode

The Xcode package installs the necessary tools which are needed during the PHP extension compilation process. Make sure you have at least Xcode v4.1 installed; the install package (“Install Xcode”) is available in your “Applications” folder.

If you are running Xcode 4.3 or above, please check you have the command line tools installed before proceeding.

Autoconf

The most recent version of Xcode does not include autoconf which is a pre-requisite. To check that you have it, run the following command in your Terminal:


autoconf --version

If you see output similar to the following, then it means you have it installed — skip to the libmcrypt section.


autoconf (GNU Autoconf) 2.61
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software. You may redistribute copies of it under the terms of
the GNU General Public License .
There is NO WARRANTY, to the extent permitted by law.

Written by David J. MacKenzie and Akim Demaille.

If you get a command not found error, then you will need to perform the following to install autoconf:


cd /tmp
curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-latest.tar.gz
tar zxvf autoconf-latest.tar.gz
cd autoconf-2.69
./configure; make
sudo make install

libmcrypt

libmcrypt is the library that provides the encryption functions. We need to install this before building the PHP extension.

  • Open up Terminal.app
  • Download libmcrypt from sourceforge
  • Unpack the archive somewhere
  • cd libmcrypt
  • ./configure
  • make
  • sudo make install

PHP Extension

Once we have libmcrypt installed, we can build the PHP extension. One important point: even though PHP 5.3.8 is now the default since Mac OS X 10.7.3, attempting to compile with these sources results in the following error:

php-5.3.8/ext/mcrypt/mcrypt.c:283: error: ‘PHP_FE_END’ undeclared here (not in a function)

Therefore, we need to use PHP 5.3.6 sources which compiles fine and still works with 10.7.3.

You should see output similar to the following:

Configuring for:
PHP Api Version:         20090626
Zend Module Api No:      20090626
Zend Extension Api No:   220090626
  • ./configure
  • make
  • sudo make install

On successful install, you will see the following message:

Installing shared extensions:     /usr/lib/php/extensions/no-debug-non-zts-20090626/

To enable the module, include the following line in your /etc/php.ini file:

extension = mcrypt.so

Finally, restart your Apache server:

sudo apachectl restart

And that’s it: you should now be able to utilise the functions, as detailed in the PHP mcrypt documentation.

P.S. – Looking for a reliable hosting provider for your PHP projects? I recommend Clook:

Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn

Mac OS X Lion PHP upgrade – php.ini and Suhosin

If you have upgraded from Snow Leopard to the new OS X Lion, you will notice PHP has also been upgraded – from 5.2 to 5.3.

A couple of points that I noticed post-install. Firstly, my existing /etc/php.ini file was moved to /etc/php.ini-5.2-previous. Restoring this was trivial:

sudo cp /etc/php.ini-5.2-previous /etc/php.ini

However, I noticed that extensions previously installed under /usr/lib/php/extensions/no-debug-non-zts-20090626/ had been removed. So, if you have extensions that you wish to still use with 5.3, they will need to be re-built.

I also noticed that Apple have included the Suhosin patch and extension. Suhosin is part of the Hardened-PHP project which aims to protect PHP applications against buffer-overflow and format string vulnerabilities. In theory, this functionality should be transparent to your application – no configuration or code changes are required.

Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn

Install mcrypt PHP extension on OS X Snow Leopard

Lock away the evil...

Please note: The following instructions apply to Mac OS X 10.6 (Snow Leopard). I have an updated guide for how to install mcrypt on 10.7 (Lion).

mcrypt is a useful extension to PHP if you would like to support a wide range of encryption algorithms within your code.

This guide explains how you can enable install mcrypt, along with the PHP extension, on Mac OS X 10.6.

Xcode

The Xcode package installs the necessary versions of tools like autoconf which is needed during the PHP extension compilation process. Make sure you have at least Xcode v3.2 installed; the install package is available on the Snow Leopard install DVD under the “Optional Installs” folder.

libmcrypt

libmcrypt is the library that provides the encryption functions. We need to install this before building the PHP extension.

  • Open up Terminal.app
  • export CFLAGS="-arch x86_64"
  • Download libmcrypt from sourceforge
  • Unpack the archive somewhere
  • cd libmcrypt
  • ./configure --disable-shared
  • make
  • sudo make install

PHP Extension

Once we have libmcrypt installed, we can build the PHP extension.

You should see output similar to the following:

Configuring for:
PHP Api Version:         20090626
Zend Module Api No:      20090626
Zend Extension Api No:   220090626
  • ./configure
  • make
  • sudo make install

On successful install, you will see the following message:

Installing shared extensions:     /usr/lib/php/extensions/no-debug-non-zts-20090626/

To enable the module, include the following line in your /etc/php.ini file:

extension = mcrypt.so

Finally, restart your Apache server:

sudo apachectl restart

And that’s it: you should now be able to utilise the functions, as detailed in the PHP mcrypt documentation.

mcrypt php extension

Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn

Install memcached PHP extension on OS X Snow Leopard

Memories

memcached is a very useful memory object caching system, which can be used to increase the performance of your dynamic scripts by caching database calls.

This guide will explain how to install the memcached system, including the PHP extension, on Mac OS X 10.6.

Xcode

The Xcode package installs the necessary versions of tools like autoconf which is needed during the PHP extension compilation process. Make sure you have Xcode 3.2 installed; the install package is available on the Snow Leopard install DVD under the “Optional Installs” folder.

libevent

libevent is a pre-requisite for memcached.

  • cd /tmp; curl -O http://www.monkey.org/~provos/libevent-1.4.12-stable.tar.gz
  • tar zxvf libevent-1.4.12-stable.tar.gz
  • cd libevent-1.4.12-stable
  • ./configure; make
  • sudo make install

memcached

memcached is the daemon responsible for actually storing and retrieving arbitrary objects for your applications.

  • cd /tmp; curl -O http://memcached.googlecode.com/files/memcached-1.4.1.tar.gz
  • tar zxvf memcached-1.4.1.tar.gz
  • cd memcached-1.4.1
  • ./configure; make
  • sudo make install

libmemcached

libmemcached is the shared library that will allow clients, in this case PHP, access the memcached daemon.

  • Download libmemcached, move to /tmp and unpack
  • cd libmemcached-0.31
  • ./configure; make
  • sudo make install

php extension

Now we are ready to prepare the PHP extension to memcached, which is available from pecl.

  • cd /tmp; pecl download memcached
  • gzip -d < memcached-1.0.0.tgz | tar -xvf -
  • cd memcached-1.0.0; phpize

You should see output similar to the following:

Configuring for:
PHP Api Version: 20090626
Zend Module Api No: 20090626
Zend Extension Api No: 220090626

  • ./configure; make
  • sudo make install

On a successful install, you will get the following message:

Installing shared extensions: /usr/lib/php/extensions/no-debug-non-zts-20090626/

Modify your php.ini configuration file and make sure you have the following line included:

extension = memcached.so

You can then restart your Apache server:

  • sudo apachectl restart

to make the memcached functionality available in your scripts.

memcached php extension

References

Glen Scott

I’m a freelance software developer with 18 years’ professional experience in web development. I specialise in creating tailor-made, web-based systems that can help your business run like clockwork. I am the Managing Director of Yellow Square Development.

More Posts

Follow Me:
TwitterFacebookLinkedIn