Skip to content

Commit 853f2b1

Browse files
authored
Merge pull request #20 from SoapBox/change/update-signature-encoding
[Change] Stop Escaping Unicode Characters
2 parents f28cf8a + b113434 commit 853f2b1

File tree

6 files changed

+837
-20
lines changed

6 files changed

+837
-20
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"ramsey/uuid": "^3.6"
2020
},
2121
"require-dev": {
22+
"jshayes/fake-requests": "^2.0",
2223
"mockery/mockery": "^0.9.9",
2324
"orchestra/testbench": "^3.4",
2425
"phpunit/phpunit": "^6.0",

src/Requests/Payload.php

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,47 @@ public function __construct($request)
2828
$this->request = $request;
2929
}
3030

31+
/**
32+
* Generates a payload with the provided properties
33+
*
34+
* @param string $identifier
35+
* @param string $method
36+
* @param string $timestamp
37+
* @param string $uri
38+
* @param string $content
39+
*
40+
* @return string
41+
*/
42+
private function generate(
43+
string $identifier,
44+
string $method,
45+
string $timestamp,
46+
string $uri,
47+
string $content
48+
) : string {
49+
$payload = [
50+
'id' => $identifier,
51+
'method' => strtoupper($method),
52+
'timestamp' => $timestamp,
53+
'uri' => rtrim($uri, '/')
54+
];
55+
56+
if (is_null(json_decode($content))) {
57+
$payload = array_merge($payload, [
58+
'content' => $content
59+
]);
60+
} else {
61+
$payload = array_merge($payload, [
62+
'content' => json_encode(
63+
json_decode($content),
64+
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
65+
)
66+
]);
67+
}
68+
69+
return json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
70+
}
71+
3172
/**
3273
* Returns the payload from a guzzle request.
3374
*
@@ -44,13 +85,13 @@ protected function generateFromPsr7Request(Psr7Request $request) : string
4485
$timestamp = isset($this->request->getHeader('X-SIGNED-TIMESTAMP')[0]) ?
4586
$this->request->getHeader('X-SIGNED-TIMESTAMP')[0] : '';
4687

47-
return json_encode([
48-
'id' => (string) $id,
49-
'method' => $this->request->getMethod(),
50-
'timestamp' => $timestamp,
51-
'uri' => (string) $this->request->getUri(),
52-
'content' => $this->request->getBody()->getContents()
53-
], JSON_UNESCAPED_SLASHES);
88+
return $this->generate(
89+
(string) $id,
90+
(string) $this->request->getMethod(),
91+
(string) $timestamp,
92+
(string) $this->request->getUri(),
93+
(string) $this->request->getBody()
94+
);
5495
}
5596

5697
/**
@@ -67,13 +108,13 @@ protected function generateFromIlluminateRequest(IlluminateRequest $request) : s
67108
$id = $this->request->headers->get('X-SIGNED-ID', '');
68109
$timestamp = $this->request->headers->get('X-SIGNED-TIMESTAMP', '');
69110

70-
return json_encode([
71-
'id' => (string) $id,
72-
'method' => $this->request->getMethod(),
73-
'timestamp' => $timestamp,
74-
'uri' => (string) $this->request->fullUrl(),
75-
'content' => $this->request->getContent()
76-
], JSON_UNESCAPED_SLASHES);
111+
return $this->generate(
112+
(string) $id,
113+
(string) $this->request->getMethod(),
114+
(string) $timestamp,
115+
(string) $this->request->fullUrl(),
116+
(string) $this->request->getContent()
117+
);
77118
}
78119

79120
/**

src/Requests/Verifier.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public function getContent($asResource = false)
142142
json_decode($content);
143143

144144
if (json_last_error() == JSON_ERROR_NONE) {
145-
return json_encode(json_decode($content), JSON_UNESCAPED_SLASHES);
145+
return json_encode(json_decode($content), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
146146
}
147147

148148
return $content;

tests/ClientTest.php

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
<?php
2+
3+
namespace Tests;
4+
5+
use Carbon\Carbon;
6+
use Ramsey\Uuid\Uuid;
7+
use JSHayes\FakeRequests\MockHandler;
8+
use Ramsey\Uuid\UuidFactoryInterface;
9+
use JSHayes\FakeRequests\ClientFactory;
10+
use SoapBox\SignedRequests\Configurations\CustomConfiguration;
11+
use SoapBox\SignedRequests\Middlewares\Guzzle\GenerateSignature;
12+
13+
class ClientTest extends TestCase
14+
{
15+
private function expectUuid4(string $uuid): void
16+
{
17+
Uuid::setFactory(new class($uuid) implements UuidFactoryInterface {
18+
public function __construct(string $uuid)
19+
{
20+
$this->uuid = $uuid;
21+
}
22+
23+
public function uuid1($node = null, $clockSeq = null)
24+
{
25+
return null;
26+
}
27+
28+
public function uuid3($ns, $name)
29+
{
30+
return null;
31+
}
32+
33+
public function uuid4()
34+
{
35+
return $this->uuid;
36+
}
37+
38+
public function uuid5($ns, $name)
39+
{
40+
return null;
41+
}
42+
43+
public function fromBytes($bytes)
44+
{
45+
return null;
46+
}
47+
48+
public function fromString($uuid)
49+
{
50+
return null;
51+
}
52+
53+
public function fromInteger($integer)
54+
{
55+
return null;
56+
}
57+
});
58+
}
59+
60+
protected function setUp()
61+
{
62+
parent::setUp();
63+
64+
$factory = new ClientFactory();
65+
$factory->setHandler($this->handler = new MockHandler());
66+
67+
$algorithmHeader = 'Algorithm';
68+
$signatureHeader = 'Signature';
69+
$signingAlgorithm = 'sha256';
70+
$signingKey = 'key';
71+
72+
$config = new CustomConfiguration(
73+
$algorithmHeader,
74+
$signatureHeader,
75+
$signingAlgorithm,
76+
$signingKey
77+
);
78+
79+
$middleware = new GenerateSignature($config);
80+
81+
$this->client = $factory->make();
82+
$this->client->getConfig('handler')->push($middleware);
83+
}
84+
85+
/**
86+
* @test
87+
*/
88+
public function it_generates_a_signature_with_a_simple_json_payload()
89+
{
90+
Carbon::setTestNow('2001-01-01 00:00:00');
91+
$this->expectUuid4('303103f5-3dca-4704-96ad-860717769ec9');
92+
93+
$uri = 'https://localhost';
94+
95+
$this->handler->expects('POST', $uri)
96+
->inspectRequest(function ($request) use ($uri) {
97+
$this->assertTrue($request->hasHeader('Algorithm'));
98+
$this->assertTrue($request->hasHeader('Signature'));
99+
$this->assertSame(
100+
'b9f912a4fc4b2952a48380579d3e4a1c55c0537ce583b3da7cc9f6c67fe4caa7',
101+
$request->getHeader('Signature')[0]
102+
);
103+
});
104+
105+
$this->client->post($uri, ['json' => ['test' => 'test']]);
106+
}
107+
108+
/**
109+
* @test
110+
*/
111+
public function it_generates_a_signature_with_a_simple_json_payload_containing_ã()
112+
{
113+
Carbon::setTestNow('2001-01-01 00:00:00');
114+
$this->expectUuid4('303103f5-3dca-4704-96ad-860717769ec9');
115+
116+
$uri = 'https://localhost';
117+
118+
$this->handler->expects('POST', $uri)
119+
->inspectRequest(function ($request) use ($uri) {
120+
$this->assertTrue($request->hasHeader('Algorithm'));
121+
$this->assertTrue($request->hasHeader('Signature'));
122+
$this->assertSame(
123+
'd35d92484222fce7e5c194381e5f53342caae6fa626cd61e3431bddc549b34e1',
124+
$request->getHeader('Signature')[0]
125+
);
126+
});
127+
128+
$this->client->post($uri, ['json' => ['test' => 'ã']]);
129+
}
130+
131+
/**
132+
* @test
133+
*/
134+
public function it_generates_a_signature_with_a_simple_json_payload_containing_好()
135+
{
136+
Carbon::setTestNow('2001-01-01 00:00:00');
137+
$this->expectUuid4('303103f5-3dca-4704-96ad-860717769ec9');
138+
139+
$uri = 'https://localhost';
140+
141+
$this->handler->expects('POST', $uri)
142+
->inspectRequest(function ($request) use ($uri) {
143+
$this->assertTrue($request->hasHeader('Algorithm'));
144+
$this->assertTrue($request->hasHeader('Signature'));
145+
$this->assertSame(
146+
'65ff94dce4894eb306a76ff0d397ec264b1c4980b57afbc3dd9526af242d239b',
147+
$request->getHeader('Signature')[0]
148+
);
149+
});
150+
151+
$this->client->post($uri, ['json' => ['test' => '']]);
152+
}
153+
154+
/**
155+
* @test
156+
*/
157+
public function it_generates_a_signature_with_a_simple_json_payload_containing_a_uri()
158+
{
159+
Carbon::setTestNow('2001-01-01 00:00:00');
160+
$this->expectUuid4('303103f5-3dca-4704-96ad-860717769ec9');
161+
162+
$uri = 'https://localhost';
163+
164+
$this->handler->expects('POST', $uri)
165+
->inspectRequest(function ($request) use ($uri) {
166+
$this->assertTrue($request->hasHeader('Algorithm'));
167+
$this->assertTrue($request->hasHeader('Signature'));
168+
$this->assertSame(
169+
'ebd68bfe7ed51c050fb92db098946cd21b7b23be6f682360a5e893840a1dc52f',
170+
$request->getHeader('Signature')[0]
171+
);
172+
});
173+
174+
$this->client->post($uri, ['json' => ['test' => $uri]]);
175+
}
176+
177+
/**
178+
* @test
179+
*/
180+
public function it_generates_a_signature_with_a_complex_json_payload()
181+
{
182+
Carbon::setTestNow('2001-01-01 00:00:00');
183+
$this->expectUuid4('303103f5-3dca-4704-96ad-860717769ec9');
184+
185+
$uri = 'https://localhost/poop';
186+
187+
$this->handler->expects('POST', $uri)
188+
->inspectRequest(function ($request) use ($uri) {
189+
$this->assertTrue($request->hasHeader('Algorithm'));
190+
$this->assertTrue($request->hasHeader('Signature'));
191+
$this->assertSame(
192+
'0c3f0c81ba1fa3df9d3e0a1d72c4d491125153c0dea8355b6d48fe7ef1a4dacc',
193+
$request->getHeader('Signature')[0]
194+
);
195+
});
196+
197+
$this->client->post(
198+
$uri,
199+
[
200+
'json' => [
201+
'users' => [
202+
['id' => 1, 'name' => 'Chris Hayes', 'email' => '[email protected]'],
203+
['id' => 2, 'name' => 'Jaspaul Bola', 'email' => '[email protected]'],
204+
['id' => 3, 'name' => 'Mr Penã 💩', 'email' => 'Mr-Penã@soapboxhq.com']
205+
]
206+
]
207+
]
208+
);
209+
}
210+
211+
/**
212+
* @test
213+
*/
214+
public function it_generates_a_signature_with_a_complex_json_payload_after_stripping_the_trailing_slash()
215+
{
216+
Carbon::setTestNow('2001-01-01 00:00:00');
217+
$this->expectUuid4('303103f5-3dca-4704-96ad-860717769ec9');
218+
219+
$uri = 'https://localhost/poop/';
220+
221+
$this->handler->expects('POST', $uri)
222+
->inspectRequest(function ($request) use ($uri) {
223+
$this->assertTrue($request->hasHeader('Algorithm'));
224+
$this->assertTrue($request->hasHeader('Signature'));
225+
$this->assertSame(
226+
'0c3f0c81ba1fa3df9d3e0a1d72c4d491125153c0dea8355b6d48fe7ef1a4dacc',
227+
$request->getHeader('Signature')[0]
228+
);
229+
});
230+
231+
$this->client->post(
232+
$uri,
233+
[
234+
'json' => [
235+
'users' => [
236+
['id' => 1, 'name' => 'Chris Hayes', 'email' => '[email protected]'],
237+
['id' => 2, 'name' => 'Jaspaul Bola', 'email' => '[email protected]'],
238+
['id' => 3, 'name' => 'Mr Penã 💩', 'email' => 'Mr-Penã@soapboxhq.com']
239+
]
240+
]
241+
]
242+
);
243+
}
244+
245+
/**
246+
* @test
247+
*/
248+
public function it_generates_a_signature_with_a_simple_json_get_payload()
249+
{
250+
Carbon::setTestNow('2001-01-01 00:00:00');
251+
$this->expectUuid4('303103f5-3dca-4704-96ad-860717769ec9');
252+
253+
$uri = 'https://localhost';
254+
255+
$this->handler->expects('GET', $uri)
256+
->inspectRequest(function ($request) use ($uri) {
257+
$this->assertTrue($request->hasHeader('Algorithm'));
258+
$this->assertTrue($request->hasHeader('Signature'));
259+
$this->assertSame(
260+
'939ada016b60aa267980a73f62e6dc583b03b35a2abf0dea5b054871d6c6a306',
261+
$request->getHeader('Signature')[0]
262+
);
263+
});
264+
265+
$this->client->get($uri, ['json' => ['payload' => 'payload']]);
266+
}
267+
268+
/**
269+
* @test
270+
*/
271+
public function it_generates_a_signature_with_a_simple_get_payload()
272+
{
273+
Carbon::setTestNow('2001-01-01 00:00:00');
274+
$this->expectUuid4('303103f5-3dca-4704-96ad-860717769ec9');
275+
276+
$uri = 'https://localhost';
277+
278+
$this->handler->expects('GET', $uri)
279+
->inspectRequest(function ($request) use ($uri) {
280+
$this->assertTrue($request->hasHeader('Algorithm'));
281+
$this->assertTrue($request->hasHeader('Signature'));
282+
$this->assertSame(
283+
'9feb58dfece796627b16f7865fc19ee6bfc5b231d49b12d83170d74d22bf9641',
284+
$request->getHeader('Signature')[0]
285+
);
286+
});
287+
288+
$this->client->get($uri, ['body' => 'payload']);
289+
}
290+
}

0 commit comments

Comments
 (0)