Skip to content

Commit 5b22fc9

Browse files
committed
Updates implementation, adds Apache license and notice, updates
documentation
1 parent 5201e44 commit 5b22fc9

File tree

7 files changed

+425
-141
lines changed

7 files changed

+425
-141
lines changed

APACHE_LICENSE_V2.md

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Apache License
2+
Version 2.0, January 2004
3+
4+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
5+
6+
## 1. Definitions.
7+
8+
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1
9+
through 9 of this document.
10+
11+
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the
12+
License.
13+
14+
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled
15+
by, or are under common control with that entity. For the purposes of this definition, "control" means
16+
(i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract
17+
or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
18+
ownership of such entity.
19+
20+
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
21+
22+
"Source" form shall mean the preferred form for making modifications, including but not limited to software
23+
source code, documentation source, and configuration files.
24+
25+
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form,
26+
including but not limited to compiled object code, generated documentation, and conversions to other media
27+
types.
28+
29+
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License,
30+
as indicated by a copyright notice that is included in or attached to the work (an example is provided in the
31+
Appendix below).
32+
33+
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from)
34+
the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent,
35+
as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not
36+
include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work
37+
and Derivative Works thereof.
38+
39+
"Contribution" shall mean any work of authorship, including the original version of the Work and any
40+
modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to
41+
Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to
42+
submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of
43+
electronic, verbal, or written communication sent to the Licensor or its representatives, including but not
44+
limited to communication on electronic mailing lists, source code control systems, and issue tracking systems
45+
that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but
46+
excluding communication that is conspicuously marked or otherwise designated in writing by the copyright
47+
owner as "Not a Contribution."
48+
49+
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been
50+
received by Licensor and subsequently incorporated within the Work.
51+
52+
## 2. Grant of Copyright License.
53+
54+
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual,
55+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
56+
Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such
57+
Derivative Works in Source or Object form.
58+
59+
## 3. Grant of Patent License.
60+
61+
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual,
62+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent
63+
license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such
64+
license applies only to those patent claims licensable by such Contributor that are necessarily infringed by
65+
their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such
66+
Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim
67+
or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work
68+
constitutes direct or contributory patent infringement, then any patent licenses granted to You under this
69+
License for that Work shall terminate as of the date such litigation is filed.
70+
71+
## 4. Redistribution.
72+
73+
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without
74+
modifications, and in Source or Object form, provided that You meet the following conditions:
75+
76+
1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
77+
78+
2. You must cause any modified files to carry prominent notices stating that You changed the files; and
79+
80+
3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent,
81+
trademark, and attribution notices from the Source form of the Work, excluding those notices that do
82+
not pertain to any part of the Derivative Works; and
83+
84+
4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that
85+
You distribute must include a readable copy of the attribution notices contained within such NOTICE
86+
file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one
87+
of the following places: within a NOTICE text file distributed as part of the Derivative Works; within
88+
the Source form or documentation, if provided along with the Derivative Works; or, within a display
89+
generated by the Derivative Works, if and wherever such third-party notices normally appear. The
90+
contents of the NOTICE file are for informational purposes only and do not modify the License. You may
91+
add Your own attribution notices within Derivative Works that You distribute, alongside or as an
92+
addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be
93+
construed as modifying the License.
94+
95+
You may add Your own copyright statement to Your modifications and may provide additional or different license
96+
terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative
97+
Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the
98+
conditions stated in this License.
99+
100+
## 5. Submission of Contributions.
101+
102+
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by
103+
You to the Licensor shall be under the terms and conditions of this License, without any additional terms or
104+
conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate
105+
license agreement you may have executed with Licensor regarding such Contributions.
106+
107+
## 6. Trademarks.
108+
109+
This License does not grant permission to use the trade names, trademarks, service marks, or product names of
110+
the Licensor, except as required for reasonable and customary use in describing the origin of the Work and
111+
reproducing the content of the NOTICE file.
112+
113+
## 7. Disclaimer of Warranty.
114+
115+
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor
116+
provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
117+
or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
118+
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the
119+
appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of
120+
permissions under this License.
121+
122+
## 8. Limitation of Liability.
123+
124+
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless
125+
required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any
126+
Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential
127+
damages of any character arising as a result of this License or out of the use or inability to use the Work
128+
(including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or
129+
any and all other commercial damages or losses), even if such Contributor has been advised of the possibility
130+
of such damages.
131+
132+
## 9. Accepting Warranty or Additional Liability.
133+
134+
While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for,
135+
acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this
136+
License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole
137+
responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold
138+
each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason
139+
of your accepting any such warranty or additional liability.
140+
141+
END OF TERMS AND CONDITIONS

NOTICE.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# AWS SDK for PHP
2+
3+
<http://aws.amazon.com/php>
4+
5+
Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License").
8+
You may not use this file except in compliance with the License.
9+
A copy of the License is located at
10+
11+
<http://aws.amazon.com/apache2.0>
12+
13+
or in the "license" file accompanying this file. This file is distributed
14+
on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
15+
express or implied. See the License for the specific language governing
16+
permissions and limitations under the License.

README.md

+57-22
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,61 @@ to handle both of those tasks.
1616

1717
## Usage
1818

19-
There are three components to this library: Client signature creation, server
20-
signature validation, and API key generation.
19+
There are three components to this library: Request signing for API consumers,
20+
request signature validation for API creators, and API key and API secret
21+
generation.
2122

22-
### Signature Creation
23+
### Request Signing
2324

2425
```php
26+
$collection = new QueryAuth\NormalizedParameterCollection();
27+
$signer = new QueryAuth\Signer($collection);
28+
$client = new QueryAuth\Client($signer);
29+
2530
$key = 'API_KEY';
2631
$secret = 'API_SECRET';
27-
$timestamp = time();
32+
$method = 'GET';
33+
$host = 'api.example.com';
34+
$path = '/resources';
35+
$params = array('type' => 'vehicles');
2836

29-
$client = new QueryAuth\Client();
30-
$signature = $client->generateSignature($key, $secret, $timestamp);
37+
$signedParameters = $client->getSignedRequestParams($key, $secret, $method, $host, $path, $params);
3138
```
3239

33-
If you plan to pass the signature along via the querystring, make sure to [url
34-
encode](http://php.net/urlencode) it first. A convenience function for
35-
generating a url encoded signature is provided.
40+
`Client::getSignedRequestParams()` returns an array of parameters to send via
41+
the querystring (for `GET` requests) or the request body. The parameters are
42+
those provided to the method (if any), plus `timestamp`, `key`, and `signature`.
3643

37-
```php
38-
$urlEncodedSignature = $client->generateUrlEncodedSignature($key, $secret, $timestamp);
39-
```
44+
**NOTE**: The signature is automatically url encoded if the method is `GET`.
4045

4146
### Signature Validation
4247

43-
Grab the API key, timestamp, and signature from the API request, then retrieve
44-
the API secret from whatever persistence layer you're using. Now validate the
45-
signature.
46-
4748
```php
48-
$key = 'API_KEY_FROM_REQUEST';
49-
$timestamp = 'TIMESTAMP_FROM_REQUEST';
50-
$signature = 'SIGNATURE_FROM_REQUEST';
51-
$secret = 'API_SECRET_FROM_PERSISTENCE_LAYER';
49+
$collection = new QueryAuth\NormalizedParameterCollection();
50+
$signer = new QueryAuth\Signer($collection);
51+
$server = new QueryAuth\Server($signer);
5252

53-
$server = new QueryAuth\Server();
54-
$isValid = $server->validateSignature($key, $secret, $timestamp, $signature);
53+
$secret = 'API_SECRET_FROM_PERSISTENCE_LAYER';
54+
$method = 'GET';
55+
$host = 'api.example.com';
56+
$path = '/resources';
57+
// querystring params or request body as an array,
58+
// which includes timestamp, key, and signature params from the client's
59+
// getSignedRequestParams method
60+
$params = 'PARAMS_FROM_REQUEST';
61+
62+
$isValid = $server->validateSignature($secret, $method, $host, $path, $params);
5563
```
5664

65+
`Server::validateSignature()` will return either true or false. It might also
66+
throw one of three exceptions:
67+
* `MaximumDriftExceededException`: If timestamp is too far in the future
68+
* `MinimumDriftExceededException`: It timestamp is too far in the past
69+
* `SignatureMissingException`: If signature is missing from request params
70+
71+
Drift defaults to 15 seconds, meaning there is a 30 second window during which the
72+
request is valid. The default value can be modified using `Server::setDrift()`.
73+
5774
### Key Generation
5875

5976
You can generate API keys and secrets in the following manner.
@@ -70,6 +87,9 @@ $key = $keyGenerator->generateKey();
7087
$secret = $keyGenerator->generateSecret();
7188
```
7289

90+
Both key and secret are generated using Anthony Ferrara's [RandomLib](https://github.com/ircmaxell/RandomLib)
91+
random string generator.
92+
7393
## Installation
7494

7595
Package installation is handled by Composer.
@@ -94,3 +114,18 @@ Package installation is handled by Composer.
94114
* Contributions should generally follow the strategy outlined in ["Contributing
95115
to a project"](https://help.github.com/articles/fork-a-repo#contributing-to-a-project)
96116
* Please submit pull requests against the `develop` branch
117+
118+
## Credits
119+
120+
* The Client, Signer, and NormalizedParameterCollection code are my own implementation of
121+
the [Signature Version 2
122+
implementation](https://github.com/aws/aws-sdk-php/blob/master/src/Aws/Common/Signature/SignatureV2.php)
123+
from the [AWS SDK for PHP
124+
2](https://github.com/aws/aws-sdk-php/blob/master/src/Aws/Common/Signature/SignatureV2.php).
125+
126+
As such, a version of the Apache License Version 2.0 is included with this
127+
distribution, and the applicable portion of the AWS SDK for PHP 2 NOTICE file
128+
is included.
129+
130+
* API key and API secret generation is handled by Anthony Ferrara's
131+
[RandomLib](https://github.com/ircmaxell/RandomLib) random string generator.

src/QueryAuth/Client.php

+32-27
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,25 @@
22

33
namespace QueryAuth;
44

5+
use QueryAuth\Signer;
6+
57
class Client
68
{
9+
/**
10+
* @var Signer
11+
*/
12+
private $signer;
13+
14+
/**
15+
* Public constructor
16+
*
17+
* @param Signer $signer Instance of singature creation class
18+
*/
19+
public function __construct(Signer $signer)
20+
{
21+
$this->signer = $signer;
22+
}
23+
724
/**
825
* Sign request params
926
*
@@ -13,49 +30,37 @@ class Client
1330
* @param string $host Host portion of API resource URL (including subdomain, excluding scheme)
1431
* @param string $path Path portion of API resource URL (excluding query and fragment)
1532
* @param array $params OPTIONAL Request params (query or POST fields), only needed if required by endpoint
16-
* @return array Signed request params
33+
* @return array Request params provided PLUS key, timestamp, and signature
1734
*/
1835
public function getSignedRequestParams($key, $secret, $method, $host, $path, array $params = array())
1936
{
2037
$params['key'] = $key;
2138
$params['timestamp'] = (int) gmdate('U');
22-
2339
// Ensure path is absolute
2440
$path = '/' . ltrim($path, '/');
25-
26-
$data = $method . "\n"
27-
. $host . "\n"
28-
. $path . "\n"
29-
. $this->getNormalizedParameterString($params);
30-
31-
$signature = \base64_encode(\hash_hmac('sha256', $data, $secret, true));
32-
33-
if ($method == 'GET') {
34-
$signature = urlencode($signature);
35-
}
36-
41+
$signature = $this->signer->createSignature($method, $host, $path, $secret, $params);
3742
$params['signature'] = $signature;
3843

3944
return $params;
4045
}
4146

4247
/**
43-
* Get request params as string, sorted alphabetically using strcmp
48+
* Get Signer
4449
*
45-
* @param array $params Array of request paramaters
46-
* @return string Normalized, rawurlencoded parameters as string
50+
* @return Signer Instance of the signature creation class
4751
*/
48-
public function getNormalizedParameterString(array $params)
52+
public function getSigner()
4953
{
50-
unset($params['signature']);
51-
uksort($params, 'strcmp');
52-
53-
$normalized = '';
54-
55-
foreach ($params as $key => $value) {
56-
$normalized .= rawurlencode($key) . '=' . rawurlencode($value) . '&';
57-
}
54+
return $this->signer;
55+
}
5856

59-
return substr($normalized, 0, -1);
57+
/**
58+
* Set Signer
59+
*
60+
* @param Signer $signer Instance of the signature creation class
61+
*/
62+
public function setSigner(Signer $signer)
63+
{
64+
$this->signer = $signer;
6065
}
6166
}

0 commit comments

Comments
 (0)