PHPackages                             jeremykendall/query-auth - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. jeremykendall/query-auth

ActiveLibrary[HTTP &amp; Networking](/categories/http)

jeremykendall/query-auth
========================

Signature generation and validation for REST API query authentication

3.1.0(9y ago)142122.8k↑75.4%12[3 PRs](https://github.com/jeremykendall/query-auth/pulls)1MITPHPPHP &gt;=5.4

Since Aug 2Pushed 7y ago14 watchersCompare

[ Source](https://github.com/jeremykendall/query-auth)[ Packagist](https://packagist.org/packages/jeremykendall/query-auth)[ RSS](/packages/jeremykendall-query-auth/feed)WikiDiscussions develop Synced yesterday

READMEChangelog (8)Dependencies (6)Versions (15)Used By (1)

Query Auth
==========

[](#query-auth)

master: [![Build Status](https://camo.githubusercontent.com/8f257b32f69b6953f1dbe1c751172f82815551c9a9141963fee8bab6620186b4/68747470733a2f2f7472617669732d63692e6f72672f6a6572656d796b656e64616c6c2f71756572792d617574682e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/jeremykendall/query-auth) develop: [![Build Status](https://camo.githubusercontent.com/51250dd28764b6565dc31aa73c175c0fe46957a486c1ce6a38ae7886315b712c/68747470733a2f2f7472617669732d63692e6f72672f6a6572656d796b656e64616c6c2f71756572792d617574682e706e673f6272616e63683d646576656c6f70)](https://travis-ci.org/jeremykendall/query-auth)

Signature generation and validation for REST API query authentication

API Query Authentication
------------------------

[](#api-query-authentication)

Most APIs require some sort of query authentication, frequently a method of signing API requests with an API key and signature. The signature is usually generated using a shared secret. When you're consuming an API, there are (hopefully) easy to follow steps to create signatures. When you're writing your own API, you have to whip up both a server-side signature validation strategy and a client-side signature creation strategy. This library endeavors to handle both of those tasks for you.

Sample Implementation
---------------------

[](#sample-implementation)

A [sample implementation of the Query Auth library](https://github.com/jeremykendall/query-auth-impl)is available in order to better demonstrate how one might employ the library.

Usage
-----

[](#usage)

There are three components to this library:

- Request signing
- Request validation
- API key and secret generation

Request signing and validation are made possible by the use of request adapters.

### Request Adapters

[](#request-adapters)

Query Auth request adapters wrap outgoing and incoming requests and adapt them to the request interface that Query Auth expects.

#### Outgoing

[](#outgoing)

Outgoing request adapters are used to facilitate request signing. There are currently two available in the `QueryAuth\Request\Adapter\Outgoing` namespace:

- `GuzzleRequestAdapter` for use with Guzzle v3
- `GuzzleHttpRequestAdapter` for use with Guzzle v4

#### Incoming

[](#incoming)

Incoming request adapters are used to facilitate request validation. There is currently one available in the `QueryAuth\Request\Adapter\Incoming` namespace:

- `SlimRequestAdapter` for use with Slim PHP v2

#### Custom

[](#custom)

If you would prefer to use an HTTP library other than Guzzle, or if you prefer to use an application framework other than Slim, you will need to write your own request adapter(s). Please refer to the existing request adapters for examples.

### Request Signing

[](#request-signing)

```
use GuzzleHttp\Client as GuzzleHttpClient;
use QueryAuth\Credentials\Credentials;
use QueryAuth\Factory;
use QueryAuth\Request\Adapter\Outgoing\GuzzleHttpRequestAdapter;

$factory = new Factory();
$requestSigner = $factory->newRequestSigner();
$credentials = new Credentials('key', 'secret');

// Create a GET request and set an endpoint
$guzzle = new GuzzleHttpClient(['base_url' => 'http://api.example.com']);
$request = $guzzle->createRequest('GET', '/endpoint');

// Sign the request
$requestSigner->signRequest(new GuzzleHttpRequestAdapter($request), $credentials);

// Send signed request
$response = $guzzle->send($request);
```

### Request Validation

[](#request-validation)

```
use QueryAuth\Credentials\Credentials;
use QueryAuth\Factory;
use QueryAuth\Request\Adapter\Incoming\SlimRequestAdapter;

$factory = new Factory();
$requestValidator = $factory->newRequestValidator();
$credentials = new Credentials('key', 'secret');

// Get the Slim request (in the context of a Slim route, hook, or middleware)
$request = $app->request;

// $isValid is a boolean
$isValid = $requestValidator->isValid(new SlimRequestAdapter($request), $credentials);
```

`RequestValidator::isValid()` will return either true or false. It might also throw one of three exceptions:

- `DriftExceededException`: It timestamp is beyond +- `RequestValidator::$drift`
- `SignatureMissingException`: If signature is missing from request params
- `TimestampMissingException`: If timestamp is missing from request params

Drift defaults to 15 seconds, meaning there is a 30 second window during which the request is valid. The default value can be modified using `RequestValidator::setDrift()`.

### Replay Attack Prevention

[](#replay-attack-prevention)

There are a number of strategies available to prevent [replay attacks](http://en.wikipedia.org/wiki/Replay_attack). The strategy in place here follows this general outline:

- Validate incoming signature
- If the signature is valid, check the storage layer to see if that combination of API key and signature have been used before
- If they have, the request is likely a replay attack and should be denied
- If they have not, persist the API key, signature, and an expiration timestamp
- Routinely purge records with a timestamp beyond the expiration time

**IMPORTANT**: The signature expiration timestamp should be greater than maximum allowable drift. Deleting a signature too soon can leave you vulnerable to a replay attack.

**NOTE**: Implementing a replay prevention strategy is optional. It is not a requirement for using this library. It is, however, *highly* recommended.

The [`QueryAuth\Storage\SignatureStorage`](https://github.com/jeremykendall/query-auth/blob/master/src/QueryAuth/Storage/SignatureStorage.php)interface is provided to aid in implementing replay attack prevention.

```
