blob: d18eaa6d7245fad252c18b9dcf6452f2a0f2e816 [file] [log] [blame]
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +01001<?php
2
3namespace OAuth2\Controller;
4
5use OAuth2\Storage\Bootstrap;
6use OAuth2\Server;
7use OAuth2\GrantType\AuthorizationCode;
8use OAuth2\GrantType\ClientCredentials;
9use OAuth2\GrantType\UserCredentials;
10use OAuth2\Scope;
11use OAuth2\Request\TestRequest;
12use OAuth2\Response;
13use PHPUnit\Framework\TestCase;
14
15class TokenControllerTest extends TestCase
16{
17 public function testNoGrantType()
18 {
19 // add the test parameters in memory
20 $server = $this->getTestServer();
21 $server->handleTokenRequest(TestRequest::createPost(), $response = new Response());
22
23 $this->assertEquals($response->getStatusCode(), 400);
24 $this->assertEquals($response->getParameter('error'), 'invalid_request');
25 $this->assertEquals($response->getParameter('error_description'), 'The grant type was not specified in the request');
26 }
27
28 public function testInvalidGrantType()
29 {
30 // add the test parameters in memory
31 $server = $this->getTestServer();
32 $request = TestRequest::createPost(array(
33 'grant_type' => 'invalid_grant_type', // invalid grant type
34 ));
35 $server->handleTokenRequest($request, $response = new Response());
36
37 $this->assertEquals($response->getStatusCode(), 400);
38 $this->assertEquals($response->getParameter('error'), 'unsupported_grant_type');
39 $this->assertEquals($response->getParameter('error_description'), 'Grant type "invalid_grant_type" not supported');
40 }
41
42 public function testNoClientId()
43 {
44 // add the test parameters in memory
45 $server = $this->getTestServer();
46 $request = TestRequest::createPost(array(
47 'grant_type' => 'authorization_code', // valid grant type
48 'code' => 'testcode',
49 ));
50 $server->handleTokenRequest($request, $response = new Response());
51
52 $this->assertEquals($response->getStatusCode(), 400);
53 $this->assertEquals($response->getParameter('error'), 'invalid_client');
54 $this->assertEquals($response->getParameter('error_description'), 'Client credentials were not found in the headers or body');
55 }
56
57 public function testNoClientSecretWithConfidentialClient()
58 {
59 // add the test parameters in memory
60 $server = $this->getTestServer();
61 $request = TestRequest::createPost(array(
62 'grant_type' => 'authorization_code', // valid grant type
63 'code' => 'testcode',
64 'client_id' => 'Test Client ID', // valid client id
65 ));
66 $server->handleTokenRequest($request, $response = new Response());
67
68 $this->assertEquals($response->getStatusCode(), 400);
69 $this->assertEquals($response->getParameter('error'), 'invalid_client');
70 $this->assertEquals($response->getParameter('error_description'), 'This client is invalid or must authenticate using a client secret');
71 }
72
73 public function testNoClientSecretWithEmptySecret()
74 {
75 // add the test parameters in memory
76 $server = $this->getTestServer();
77 $request = TestRequest::createPost(array(
78 'grant_type' => 'authorization_code', // valid grant type
79 'code' => 'testcode-empty-secret',
80 'client_id' => 'Test Client ID Empty Secret', // valid client id
81 ));
82 $server->handleTokenRequest($request, $response = new Response());
83
84 $this->assertEquals($response->getStatusCode(), 200);
85 }
86
87 public function testInvalidClientId()
88 {
89 // add the test parameters in memory
90 $server = $this->getTestServer();
91 $request = TestRequest::createPost(array(
92 'grant_type' => 'authorization_code', // valid grant type
93 'code' => 'testcode',
94 'client_id' => 'Fake Client ID', // invalid client id
95 'client_secret' => 'TestSecret', // valid client secret
96 ));
97 $server->handleTokenRequest($request, $response = new Response());
98
99 $this->assertEquals($response->getStatusCode(), 400);
100 $this->assertEquals($response->getParameter('error'), 'invalid_client');
101 $this->assertEquals($response->getParameter('error_description'), 'The client credentials are invalid');
102 }
103
104 public function testInvalidClientSecret()
105 {
106 // add the test parameters in memory
107 $server = $this->getTestServer();
108 $request = TestRequest::createPost(array(
109 'grant_type' => 'authorization_code', // valid grant type
110 'code' => 'testcode',
111 'client_id' => 'Test Client ID', // valid client id
112 'client_secret' => 'Fake Client Secret', // invalid client secret
113 ));
114 $server->handleTokenRequest($request, $response = new Response());
115
116 $this->assertEquals($response->getStatusCode(), 400);
117 $this->assertEquals($response->getParameter('error'), 'invalid_client');
118 $this->assertEquals($response->getParameter('error_description'), 'The client credentials are invalid');
119 }
120
121 public function testValidTokenResponse()
122 {
123 // add the test parameters in memory
124 $server = $this->getTestServer();
125 $request = TestRequest::createPost(array(
126 'grant_type' => 'authorization_code', // valid grant type
127 'client_id' => 'Test Client ID', // valid client id
128 'client_secret' => 'TestSecret', // valid client secret
129 'code' => 'testcode', // valid authorization code
130 ));
131 $server->handleTokenRequest($request, $response = new Response());
132
133 $this->assertTrue($response instanceof Response);
134 $this->assertEquals($response->getStatusCode(), 200);
135 $this->assertNull($response->getParameter('error'));
136 $this->assertNull($response->getParameter('error_description'));
137 $this->assertNotNull($response->getParameter('access_token'));
138 $this->assertNotNull($response->getParameter('expires_in'));
139 $this->assertNotNull($response->getParameter('token_type'));
140 }
141
142 public function testValidClientIdScope()
143 {
144 // add the test parameters in memory
145 $server = $this->getTestServer();
146 $request = TestRequest::createPost(array(
147 'grant_type' => 'authorization_code', // valid grant type
148 'code' => 'testcode',
149 'client_id' => 'Test Client ID', // valid client id
150 'client_secret' => 'TestSecret', // valid client secret
151 'scope' => 'clientscope1 clientscope2'
152 ));
153 $server->handleTokenRequest($request, $response = new Response());
154
155 $this->assertEquals($response->getStatusCode(), 200);
156 $this->assertNull($response->getParameter('error'));
157 $this->assertNull($response->getParameter('error_description'));
158 $this->assertEquals('clientscope1 clientscope2', $response->getParameter('scope'));
159 }
160
161 public function testInvalidClientIdScope()
162 {
163 // add the test parameters in memory
164 $server = $this->getTestServer();
165 $request = TestRequest::createPost(array(
166 'grant_type' => 'authorization_code', // valid grant type
167 'code' => 'testcode-with-scope',
168 'client_id' => 'Test Client ID', // valid client id
169 'client_secret' => 'TestSecret', // valid client secret
170 'scope' => 'clientscope3'
171 ));
172 $server->handleTokenRequest($request, $response = new Response());
173
174 $this->assertEquals($response->getStatusCode(), 400);
175 $this->assertEquals($response->getParameter('error'), 'invalid_scope');
176 $this->assertEquals($response->getParameter('error_description'), 'The scope requested is invalid for this request');
177 }
178
179 public function testEnforceScope()
180 {
181 $storage = Bootstrap::getInstance()->getMemoryStorage();
182 $server = new Server($storage);
183 $server->addGrantType(new ClientCredentials($storage));
184
185 $scope = new Scope(array(
186 'default_scope' => false,
187 'supported_scopes' => array('testscope')
188 ));
189 $server->setScopeUtil($scope);
190
191 $request = TestRequest::createPost(array(
192 'grant_type' => 'client_credentials', // valid grant type
193 'client_id' => 'Test Client ID', // valid client id
194 'client_secret' => 'TestSecret', // valid client secret
195 ));
196 $response = $server->handleTokenRequest($request);
197
198 $this->assertEquals($response->getStatusCode(), 400);
199 $this->assertEquals($response->getParameter('error'), 'invalid_scope');
200 $this->assertEquals($response->getParameter('error_description'), 'This application requires you specify a scope parameter');
201 }
202
203 public function testCanReceiveAccessTokenUsingPasswordGrantTypeWithoutClientSecret()
204 {
205 // add the test parameters in memory
206 $storage = Bootstrap::getInstance()->getMemoryStorage();
207 $server = new Server($storage);
208 $server->addGrantType(new UserCredentials($storage));
209
210 $request = TestRequest::createPost(array(
211 'grant_type' => 'password', // valid grant type
212 'client_id' => 'Test Client ID For Password Grant', // valid client id
213 'username' => 'johndoe', // valid username
214 'password' => 'password', // valid password for username
215 ));
216 $server->handleTokenRequest($request, $response = new Response());
217
218 $this->assertTrue($response instanceof Response);
219 $this->assertEquals(200, $response->getStatusCode(), var_export($response, 1));
220 $this->assertNull($response->getParameter('error'));
221 $this->assertNull($response->getParameter('error_description'));
222 $this->assertNotNull($response->getParameter('access_token'));
223 $this->assertNotNull($response->getParameter('expires_in'));
224 $this->assertNotNull($response->getParameter('token_type'));
225 }
226
227 public function testInvalidTokenTypeHintForRevoke()
228 {
229 $server = $this->getTestServer();
230
231 $request = TestRequest::createPost(array(
232 'token_type_hint' => 'foo',
233 'token' => 'sometoken'
234 ));
235
236 $server->handleRevokeRequest($request, $response = new Response());
237
238 $this->assertTrue($response instanceof Response);
239 $this->assertEquals(400, $response->getStatusCode(), var_export($response, 1));
240 $this->assertEquals($response->getParameter('error'), 'invalid_request');
241 $this->assertEquals($response->getParameter('error_description'), 'Token type hint must be either \'access_token\' or \'refresh_token\'');
242 }
243
244 public function testMissingTokenForRevoke()
245 {
246 $server = $this->getTestServer();
247
248 $request = TestRequest::createPost(array(
249 'token_type_hint' => 'access_token'
250 ));
251
252 $server->handleRevokeRequest($request, $response = new Response());
253 $this->assertTrue($response instanceof Response);
254 $this->assertEquals(400, $response->getStatusCode(), var_export($response, 1));
255 $this->assertEquals($response->getParameter('error'), 'invalid_request');
256 $this->assertEquals($response->getParameter('error_description'), 'Missing token parameter to revoke');
257 }
258
259 public function testInvalidRequestMethodForRevoke()
260 {
261 $server = $this->getTestServer();
262
263 $request = new TestRequest();
264 $request->setQuery(array(
265 'token_type_hint' => 'access_token'
266 ));
267
268 $server->handleRevokeRequest($request, $response = new Response());
269 $this->assertTrue($response instanceof Response);
270 $this->assertEquals(405, $response->getStatusCode(), var_export($response, 1));
271 $this->assertEquals($response->getParameter('error'), 'invalid_request');
272 $this->assertEquals($response->getParameter('error_description'), 'The request method must be POST when revoking an access token');
273 }
274
275 public function testCanUseCrossOriginRequestForRevoke()
276 {
277 $server = $this->getTestServer();
278
279 $request = new TestRequest();
280 $request->setMethod('OPTIONS');
281
282 $server->handleRevokeRequest($request, $response = new Response());
283 $this->assertTrue($response instanceof Response);
284 $this->assertEquals(200, $response->getStatusCode(), var_export($response, 1));
285 $this->assertEquals($response->getHttpHeader('Allow'), 'POST, OPTIONS');
286 }
287
288 public function testInvalidRequestMethodForAccessToken()
289 {
290 $server = $this->getTestServer();
291
292 $request = new TestRequest();
293 $request->setQuery(array(
294 'token_type_hint' => 'access_token'
295 ));
296
297 $server->handleTokenRequest($request, $response = new Response());
298 $this->assertTrue($response instanceof Response);
299 $this->assertEquals(405, $response->getStatusCode(), var_export($response, 1));
300 $this->assertEquals($response->getParameter('error'), 'invalid_request');
301 $this->assertEquals($response->getParameter('error_description'), 'The request method must be POST when requesting an access token');
302 }
303
304 public function testCanUseCrossOriginRequestForAccessToken()
305 {
306 $server = $this->getTestServer();
307
308 $request = new TestRequest();
309 $request->setMethod('OPTIONS');
310
311 $server->handleTokenRequest($request, $response = new Response());
312 $this->assertTrue($response instanceof Response);
313 $this->assertEquals(200, $response->getStatusCode(), var_export($response, 1));
314 $this->assertEquals($response->getHttpHeader('Allow'), 'POST, OPTIONS');
315 }
316
317 public function testCreateController()
318 {
319 $storage = Bootstrap::getInstance()->getMemoryStorage();
320 $accessToken = new \OAuth2\ResponseType\AccessToken($storage);
321 $controller = new TokenController($accessToken, $storage);
322 }
323
324 private function getTestServer()
325 {
326 $storage = Bootstrap::getInstance()->getMemoryStorage();
327 $server = new Server($storage);
328 $server->addGrantType(new AuthorizationCode($storage));
329
330 return $server;
331 }
332}