1 | <?php |
||||
2 | namespace TraderInteractive\Api; |
||||
3 | |||||
4 | use TraderInteractive\Util; |
||||
5 | use TraderInteractive\Util\Arrays; |
||||
6 | use TraderInteractive\Util\Http; |
||||
7 | use GuzzleHttp\Psr7\Request; |
||||
8 | use Psr\Http\Message\RequestInterface; |
||||
9 | use Psr\Http\Message\ResponseInterface; |
||||
10 | |||||
11 | /** |
||||
12 | * Layer for OAuth2 Authentication |
||||
13 | */ |
||||
14 | final class Authentication |
||||
15 | { |
||||
16 | /** |
||||
17 | * Function to create a Request object for obtaining a new token from the API |
||||
18 | * |
||||
19 | * @var callable |
||||
20 | */ |
||||
21 | private $getTokenRequestFunc; |
||||
22 | |||||
23 | /** |
||||
24 | * Private constructor to safeguard undeclared functions |
||||
25 | * |
||||
26 | * @param callable $getTokenRequestFunc Function to create a Request object for obtaining a new token from the API |
||||
27 | */ |
||||
28 | private function __construct(callable $getTokenRequestFunc) |
||||
29 | { |
||||
30 | $this->getTokenRequestFunc = $getTokenRequestFunc; |
||||
31 | } |
||||
32 | |||||
33 | /** |
||||
34 | * Creates a new instance of Authentication for Client Credentials grant type |
||||
35 | * |
||||
36 | * @param string $clientId The oauth client id |
||||
37 | * @param string $clientSecret The oauth client secret |
||||
38 | * @param string $refreshResource The refresh token resource of the API Only needed since apigee doesnt use the |
||||
39 | * token resource that is in the oauth2 spec |
||||
40 | * @param string $tokenResource The access token resource of the API |
||||
41 | * |
||||
42 | * @return Authentication |
||||
43 | */ |
||||
44 | public static function createClientCredentials( |
||||
45 | string $clientId, |
||||
46 | string $clientSecret, |
||||
47 | string $refreshResource = 'token', |
||||
48 | string $tokenResource = 'token' |
||||
49 | ) : Authentication { |
||||
50 | $getTokenRequestFunc = function ( |
||||
51 | string $baseUrl, |
||||
52 | string $refreshToken = null |
||||
53 | ) use ( |
||||
54 | $clientId, |
||||
55 | $clientSecret, |
||||
56 | $refreshResource, |
||||
57 | $tokenResource |
||||
58 | ) { |
||||
59 | if ($refreshToken !== null) { |
||||
60 | return self::getRefreshTokenRequest( |
||||
61 | $baseUrl, |
||||
62 | $clientId, |
||||
63 | $clientSecret, |
||||
64 | $refreshResource, |
||||
65 | $refreshToken |
||||
66 | ); |
||||
67 | } |
||||
68 | |||||
69 | $data = ['client_id' => $clientId, 'client_secret' => $clientSecret, 'grant_type' => 'client_credentials']; |
||||
70 | return new Request( |
||||
71 | 'POST', |
||||
72 | "{$baseUrl}/{$tokenResource}", |
||||
73 | ['Content-Type' => 'application/x-www-form-urlencoded'], |
||||
74 | Http::buildQueryString($data) |
||||
75 | ); |
||||
76 | }; |
||||
77 | |||||
78 | return new self($getTokenRequestFunc); |
||||
79 | } |
||||
80 | |||||
81 | /** |
||||
82 | * Creates a new instance of Authentication for Owner Credentials grant type |
||||
83 | * |
||||
84 | * @param string $clientId The oauth client id |
||||
85 | * @param string $clientSecret The oauth client secret |
||||
86 | * @param string $username The oauth username |
||||
87 | * @param string $password The oauth password |
||||
88 | * @param string $refreshResource The refresh token resource of the API. Only needed since apigee doesnt use the |
||||
89 | * token resource that is in the oauth2 spec |
||||
90 | * @param string $tokenResource The access token resource of the API |
||||
91 | * |
||||
92 | * @return Authentication |
||||
93 | */ |
||||
94 | public static function createOwnerCredentials( |
||||
95 | string $clientId, |
||||
96 | string $clientSecret, |
||||
97 | string $username, |
||||
98 | string $password, |
||||
99 | string $refreshResource = 'token', |
||||
100 | string $tokenResource = 'token' |
||||
101 | ) : Authentication { |
||||
102 | $getTokenRequestFunc = function ( |
||||
103 | string $baseUrl, |
||||
104 | string $refreshToken = null |
||||
105 | ) use ( |
||||
106 | $clientId, |
||||
107 | $clientSecret, |
||||
108 | $username, |
||||
109 | $password, |
||||
110 | $refreshResource, |
||||
111 | $tokenResource |
||||
112 | ) { |
||||
113 | if ($refreshToken !== null) { |
||||
114 | return self::getRefreshTokenRequest( |
||||
115 | $baseUrl, |
||||
116 | $clientId, |
||||
117 | $clientSecret, |
||||
118 | $refreshResource, |
||||
119 | $refreshToken |
||||
120 | ); |
||||
121 | } |
||||
122 | |||||
123 | $data = [ |
||||
124 | 'client_id' => $clientId, |
||||
125 | 'client_secret' => $clientSecret, |
||||
126 | 'username' => $username, |
||||
127 | 'password' => $password, |
||||
128 | 'grant_type' => 'password', |
||||
129 | ]; |
||||
130 | return new Request( |
||||
131 | 'POST', |
||||
132 | "{$baseUrl}/{$tokenResource}", |
||||
133 | ['Content-Type' => 'application/x-www-form-urlencoded'], |
||||
134 | Http::buildQueryString($data) |
||||
135 | ); |
||||
136 | }; |
||||
137 | |||||
138 | return new self($getTokenRequestFunc); |
||||
139 | } |
||||
140 | |||||
141 | /** |
||||
142 | * Creates a new instance of Authentication for API Gateway Client Credentials grant type |
||||
143 | * |
||||
144 | * @param string $clientId The oauth client id |
||||
145 | * @param string $clientSecret The oauth client secret |
||||
146 | * @param string $authUrl The oauth auth url |
||||
147 | * |
||||
148 | * @return Authentication |
||||
149 | */ |
||||
150 | public static function createApiGatewayClientCredentials( |
||||
151 | string $clientId, |
||||
152 | string $clientSecret, |
||||
153 | string $authUrl |
||||
154 | ) : Authentication { |
||||
155 | $getTokenRequestFunc = function ( |
||||
156 | string $unusedBaseUrl, |
||||
0 ignored issues
–
show
|
|||||
157 | string $unusedRefreshToken = null |
||||
0 ignored issues
–
show
The parameter
$unusedRefreshToken is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
158 | ) use ( |
||||
159 | $clientId, |
||||
160 | $clientSecret, |
||||
161 | $authUrl |
||||
162 | ) { |
||||
163 | $data = ['client_id' => $clientId, 'client_secret' => $clientSecret, 'grant_type' => 'client_credentials']; |
||||
164 | return new Request( |
||||
165 | 'POST', |
||||
166 | $authUrl, |
||||
167 | ['Content-Type' => 'application/x-www-form-urlencoded'], |
||||
168 | Http::buildQueryString($data) |
||||
169 | ); |
||||
170 | }; |
||||
171 | |||||
172 | return new self($getTokenRequestFunc); |
||||
173 | } |
||||
174 | |||||
175 | /** |
||||
176 | * Extracts an access token from the given API response |
||||
177 | * |
||||
178 | * @param ResponseInterface $response The API response containing the access token |
||||
179 | * |
||||
180 | * @return array Array containing the access token, refresh token and expires timestamp |
||||
181 | */ |
||||
182 | public static function parseTokenResponse(ResponseInterface $response) |
||||
183 | { |
||||
184 | $parsedJson = json_decode((string)$response->getBody(), true); |
||||
185 | Util::ensureNot('invalid_client', Arrays::get($parsedJson, 'error'), 'Invalid Credentials'); |
||||
186 | Util::ensure( |
||||
187 | 200, |
||||
188 | $response->getStatusCode(), |
||||
189 | Arrays::get($parsedJson, 'error_description', 'Unknown API error') |
||||
190 | ); |
||||
191 | return [ |
||||
192 | $parsedJson['access_token'], |
||||
193 | Arrays::get($parsedJson, 'refresh_token'), |
||||
194 | time() + (int)$parsedJson['expires_in'], |
||||
195 | ]; |
||||
196 | } |
||||
197 | |||||
198 | /** |
||||
199 | * Creates a Request object for obtaining a new token from the API |
||||
200 | * |
||||
201 | * @param string $baseUrl The base url of the API |
||||
202 | * @param string|null $refreshToken The refresh token of the API |
||||
203 | * |
||||
204 | * @return RequestInterface |
||||
205 | */ |
||||
206 | public function getTokenRequest(string $baseUrl, string $refreshToken = null) : RequestInterface |
||||
207 | { |
||||
208 | return call_user_func($this->getTokenRequestFunc, $baseUrl, $refreshToken); |
||||
209 | } |
||||
210 | |||||
211 | /** |
||||
212 | * Build a refresh token request |
||||
213 | * |
||||
214 | * @param string $baseUrl API base url |
||||
215 | * @param string $clientId The client id |
||||
216 | * @param string $clientSecret The client secret |
||||
217 | * @param string $refreshResource The refresh token resource of the API |
||||
218 | * Only needed since apigee doesnt use the token resource that is in the oauth2 spec |
||||
219 | * @param string $refreshToken The refresh token of the API |
||||
220 | * |
||||
221 | * @return RequestInterface The built token refresh request |
||||
222 | */ |
||||
223 | private static function getRefreshTokenRequest( |
||||
224 | string $baseUrl, |
||||
225 | string $clientId, |
||||
226 | string $clientSecret, |
||||
227 | string $refreshResource, |
||||
228 | string $refreshToken |
||||
229 | ) : RequestInterface { |
||||
230 | //NOTE client_id and client_secret are needed for Apigee but are not in the oauth2 spec |
||||
231 | $data = [ |
||||
232 | 'client_id' => $clientId, |
||||
233 | 'client_secret' => $clientSecret, |
||||
234 | 'refresh_token' => $refreshToken, |
||||
235 | 'grant_type' => 'refresh_token', |
||||
236 | ]; |
||||
237 | |||||
238 | //NOTE the oauth2 spec says the refresh resource should be the same as the token resource, which is impossible |
||||
239 | //in Apigee and why the $refreshResource variable exists |
||||
240 | return new Request( |
||||
241 | 'POST', |
||||
242 | "{$baseUrl}/{$refreshResource}", |
||||
243 | ['Content-Type' => 'application/x-www-form-urlencoded'], |
||||
244 | Http::buildQueryString($data) |
||||
245 | ); |
||||
246 | } |
||||
247 | } |
||||
248 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.