1
|
|
|
<?php namespace nyx\auth\id\protocols\oauth1\signers; |
2
|
|
|
|
3
|
|
|
// External dependencies |
4
|
|
|
use Psr\Http\Message\RequestInterface as Request; |
5
|
|
|
|
6
|
|
|
// Internal dependencies |
7
|
|
|
use nyx\auth\id\protocols\oauth1; |
8
|
|
|
use nyx\auth; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* OAuth 1.0a RSA-SHA1 Request Signer |
12
|
|
|
* |
13
|
|
|
* Note: Relies on the OpenSSL extension being available but will *not throw* on its own until a function |
14
|
|
|
* provided by the OpenSSL extension gets invoked. |
15
|
|
|
* |
16
|
|
|
* @package Nyx\Auth |
17
|
|
|
* @version 0.1.0 |
18
|
|
|
* @author Michal Chojnacki <[email protected]> |
19
|
|
|
* @copyright 2012-2017 Nyx Dev Team |
20
|
|
|
* @link https://github.com/unyx/nyx |
21
|
|
|
* ---- |
22
|
|
|
* @see https://oauth.net/core/1.0a/#anchor18 (Spec #9.3 RSA-SHA1) |
23
|
|
|
*/ |
24
|
|
|
class RsaSha1 extends oauth1\Signer |
25
|
|
|
{ |
26
|
|
|
/** |
27
|
|
|
* {@inheritDoc} |
28
|
|
|
*/ |
29
|
|
|
public function getSignatureMethod() : string |
30
|
|
|
{ |
31
|
|
|
return oauth1\interfaces\Signer::METHOD_RSA_SHA1; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* {@inheritDoc} |
36
|
|
|
* |
37
|
|
|
* Note: The OAUth Token is entirely ignored in this signing flow, as per spec. |
38
|
|
|
*/ |
39
|
|
|
public function sign(Request $request, array $params, auth\id\credentials\Client $client, auth\interfaces\Credentials $token = null) : string |
40
|
|
|
{ |
41
|
|
|
if (false === $key = $this->createKey($client)) { |
42
|
|
|
throw new \RuntimeException('Failed to open the private key (invalid passphrase?).'); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
// openssl_sign() populates this by reference so we need a holder value. |
46
|
|
|
$signature = ''; |
47
|
|
|
$success = openssl_sign($this->buildBaseString($request, $params), $signature, $key, OPENSSL_ALGO_SHA1); |
48
|
|
|
|
49
|
|
|
// Free the resource in any case, before the potential throw. |
50
|
|
|
openssl_free_key($key); |
51
|
|
|
|
52
|
|
|
if (false === $success) { |
53
|
|
|
throw new \RuntimeException('Failed to sign the Request with the provided private key.'); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
return base64_encode($signature); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* {@inheritDoc} |
61
|
|
|
* |
62
|
|
|
* @return resource|bool |
63
|
|
|
*/ |
64
|
|
|
protected function createKey(auth\id\credentials\Client $client, auth\interfaces\Credentials $token = null) |
65
|
|
|
{ |
66
|
|
|
// If it's a nested Credentials instance, we assume the id is the key (either the full key or |
67
|
|
|
// a path starting with "file://", as understood by openssl_pkey_get_private(), and the secret is the |
68
|
|
|
// key's passphrase). |
69
|
|
|
if (($key = $client->getSecret()) instanceof auth\interfaces\Credentials) { |
70
|
|
|
return openssl_pkey_get_private($key->getId(), $key->getSecret()); |
|
|
|
|
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
return openssl_pkey_get_private($key); |
|
|
|
|
74
|
|
|
} |
75
|
|
|
} |
76
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.