diff options
Diffstat (limited to 'library/oauth2/test/OAuth2/Controller')
3 files changed, 956 insertions, 0 deletions
diff --git a/library/oauth2/test/OAuth2/Controller/AuthorizeControllerTest.php b/library/oauth2/test/OAuth2/Controller/AuthorizeControllerTest.php new file mode 100644 index 000000000..3bfc760e4 --- /dev/null +++ b/library/oauth2/test/OAuth2/Controller/AuthorizeControllerTest.php @@ -0,0 +1,492 @@ +<?php + +namespace OAuth2\Controller; + +use OAuth2\Storage\Memory; +use OAuth2\Scope; +use OAuth2\Storage\Bootstrap; +use OAuth2\Server; +use OAuth2\GrantType\AuthorizationCode; +use OAuth2\Request; +use OAuth2\Response; +use OAuth2\Request\TestRequest; + +class AuthorizeControllerTest extends \PHPUnit_Framework_TestCase +{ + public function testNoClientIdResponse() + { + $server = $this->getTestServer(); + $request = new Request(); + $server->handleAuthorizeRequest($request, $response = new Response(), false); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_client'); + $this->assertEquals($response->getParameter('error_description'), 'No client id supplied'); + } + + public function testInvalidClientIdResponse() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Fake Client ID', // invalid client id + )); + $server->handleAuthorizeRequest($request, $response = new Response(), false); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_client'); + $this->assertEquals($response->getParameter('error_description'), 'The client id supplied is invalid'); + } + + public function testNoRedirectUriSuppliedOrStoredResponse() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + )); + $server->handleAuthorizeRequest($request, $response = new Response(), false); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_uri'); + $this->assertEquals($response->getParameter('error_description'), 'No redirect URI was supplied or stored'); + } + + public function testNoResponseTypeResponse() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com', // valid redirect URI + )); + $server->handleAuthorizeRequest($request, $response = new Response(), false); + + $this->assertEquals($response->getStatusCode(), 302); + $location = $response->getHttpHeader('Location'); + $parts = parse_url($location); + parse_str($parts['query'], $query); + + $this->assertEquals($query['error'], 'invalid_request'); + $this->assertEquals($query['error_description'], 'Invalid or missing response type'); + } + + public function testInvalidResponseTypeResponse() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com', // valid redirect URI + 'response_type' => 'invalid', // invalid response type + )); + $server->handleAuthorizeRequest($request, $response = new Response(), false); + + $this->assertEquals($response->getStatusCode(), 302); + $location = $response->getHttpHeader('Location'); + $parts = parse_url($location); + parse_str($parts['query'], $query); + + $this->assertEquals($query['error'], 'invalid_request'); + $this->assertEquals($query['error_description'], 'Invalid or missing response type'); + } + + public function testRedirectUriFragmentResponse() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com#fragment', // valid redirect URI + 'response_type' => 'code', // invalid response type + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_uri'); + $this->assertEquals($response->getParameter('error_description'), 'The redirect URI must not contain a fragment'); + } + + public function testEnforceState() + { + $server = $this->getTestServer(array('enforce_state' => true)); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com', // valid redirect URI + 'response_type' => 'code', + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + $location = $response->getHttpHeader('Location'); + $parts = parse_url($location); + parse_str($parts['query'], $query); + + $this->assertEquals($query['error'], 'invalid_request'); + $this->assertEquals($query['error_description'], 'The state parameter is required'); + } + + public function testDoNotEnforceState() + { + $server = $this->getTestServer(array('enforce_state' => false)); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com', // valid redirect URI + 'response_type' => 'code', + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + $this->assertNotContains('error', $response->getHttpHeader('Location')); + } + + public function testEnforceScope() + { + $server = $this->getTestServer(); + $scopeStorage = new Memory(array('default_scope' => false, 'supported_scopes' => array('testscope'))); + $server->setScopeUtil(new Scope($scopeStorage)); + + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com', // valid redirect URI + 'response_type' => 'code', + 'state' => 'xyz', + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + $parts = parse_url($response->getHttpHeader('Location')); + parse_str($parts['query'], $query); + + $this->assertEquals($query['error'], 'invalid_client'); + $this->assertEquals($query['error_description'], 'This application requires you specify a scope parameter'); + + $request->query['scope'] = 'testscope'; + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + $this->assertNotContains('error', $response->getHttpHeader('Location')); + } + + public function testInvalidRedirectUri() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Test Client ID with Redirect Uri', // valid client id + 'redirect_uri' => 'http://adobe.com', // invalid redirect URI + 'response_type' => 'code', + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'redirect_uri_mismatch'); + $this->assertEquals($response->getParameter('error_description'), 'The redirect URI provided is missing or does not match'); + } + + public function testInvalidRedirectUriApprovedByBuggyRegisteredUri() + { + $server = $this->getTestServer(); + $server->setConfig('require_exact_redirect_uri', false); + $request = new Request(array( + 'client_id' => 'Test Client ID with Buggy Redirect Uri', // valid client id + 'redirect_uri' => 'http://adobe.com', // invalid redirect URI + 'response_type' => 'code', + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'redirect_uri_mismatch'); + $this->assertEquals($response->getParameter('error_description'), 'The redirect URI provided is missing or does not match'); + } + + public function testNoRedirectUriWithMultipleRedirectUris() + { + $server = $this->getTestServer(); + + // create a request with no "redirect_uri" in querystring + $request = new Request(array( + 'client_id' => 'Test Client ID with Multiple Redirect Uris', // valid client id + 'response_type' => 'code', + )); + + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_uri'); + $this->assertEquals($response->getParameter('error_description'), 'A redirect URI must be supplied when multiple redirect URIs are registered'); + } + + public function testRedirectUriWithValidRedirectUri() + { + $server = $this->getTestServer(); + + // create a request with no "redirect_uri" in querystring + $request = new Request(array( + 'client_id' => 'Test Client ID with Redirect Uri Parts', // valid client id + 'response_type' => 'code', + 'redirect_uri' => 'http://user:pass@brentertainment.com:2222/authorize/cb?auth_type=oauth&test=true', + 'state' => 'xyz', + )); + + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + $this->assertContains('code', $response->getHttpHeader('Location')); + } + + public function testRedirectUriWithDifferentQueryAndExactMatchRequired() + { + $server = $this->getTestServer(array('require_exact_redirect_uri' => true)); + + // create a request with no "redirect_uri" in querystring + $request = new Request(array( + 'client_id' => 'Test Client ID with Redirect Uri Parts', // valid client id + 'response_type' => 'code', + 'redirect_uri' => 'http://user:pass@brentertainment.com:2222/authorize/cb?auth_type=oauth&test=true&hereisa=querystring', + )); + + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'redirect_uri_mismatch'); + $this->assertEquals($response->getParameter('error_description'), 'The redirect URI provided is missing or does not match'); + } + + public function testRedirectUriWithDifferentQueryAndExactMatchNotRequired() + { + $server = $this->getTestServer(array('require_exact_redirect_uri' => false)); + + // create a request with no "redirect_uri" in querystring + $request = new Request(array( + 'client_id' => 'Test Client ID with Redirect Uri Parts', // valid client id + 'response_type' => 'code', + 'redirect_uri' => 'http://user:pass@brentertainment.com:2222/authorize/cb?auth_type=oauth&test=true&hereisa=querystring', + 'state' => 'xyz', + )); + + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + $this->assertContains('code', $response->getHttpHeader('Location')); + } + + public function testMultipleRedirectUris() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Test Client ID with Multiple Redirect Uris', // valid client id + 'redirect_uri' => 'http://brentertainment.com', // valid redirect URI + 'response_type' => 'code', + 'state' => 'xyz' + )); + + $server->handleAuthorizeRequest($request, $response = new Response(), true); + $this->assertEquals($response->getStatusCode(), 302); + $this->assertContains('code', $response->getHttpHeader('Location')); + + // call again with different (but still valid) redirect URI + $request->query['redirect_uri'] = 'http://morehazards.com'; + + $server->handleAuthorizeRequest($request, $response = new Response(), true); + $this->assertEquals($response->getStatusCode(), 302); + $this->assertContains('code', $response->getHttpHeader('Location')); + } + + /** + * @see http://tools.ietf.org/html/rfc6749#section-4.1.3 + * @see https://github.com/bshaffer/oauth2-server-php/issues/163 + */ + public function testNoRedirectUriSuppliedDoesNotRequireTokenRedirectUri() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Test Client ID with Redirect Uri', // valid client id + 'response_type' => 'code', + 'state' => 'xyz', + )); + + $server->handleAuthorizeRequest($request, $response = new Response(), true); + $this->assertEquals($response->getStatusCode(), 302); + $this->assertContains('state', $response->getHttpHeader('Location')); + $this->assertStringStartsWith('http://brentertainment.com?code=', $response->getHttpHeader('Location')); + + $parts = parse_url($response->getHttpHeader('Location')); + parse_str($parts['query'], $query); + + // call token endpoint with no redirect_uri supplied + $request = TestRequest::createPost(array( + 'client_id' => 'Test Client ID with Redirect Uri', // valid client id + 'client_secret' => 'TestSecret2', + 'grant_type' => 'authorization_code', + 'code' => $query['code'], + )); + + $server->handleTokenRequest($request, $response = new Response(), true); + $this->assertEquals($response->getStatusCode(), 200); + $this->assertNotNull($response->getParameter('access_token')); + } + + public function testUserDeniesAccessResponse() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com', // valid redirect URI + 'response_type' => 'code', + 'state' => 'xyz', + )); + $server->handleAuthorizeRequest($request, $response = new Response(), false); + + $this->assertEquals($response->getStatusCode(), 302); + $location = $response->getHttpHeader('Location'); + $parts = parse_url($location); + parse_str($parts['query'], $query); + + $this->assertEquals($query['error'], 'access_denied'); + $this->assertEquals($query['error_description'], 'The user denied access to your application'); + } + + public function testCodeQueryParamIsSet() + { + $server = $this->getTestServer(); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com', // valid redirect URI + 'response_type' => 'code', + 'state' => 'xyz', + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + $location = $response->getHttpHeader('Location'); + $parts = parse_url($location); + parse_str($parts['query'], $query); + + $location = $response->getHttpHeader('Location'); + $parts = parse_url($location); + + $this->assertEquals('http', $parts['scheme']); // same as passed in to redirect_uri + $this->assertEquals('adobe.com', $parts['host']); // same as passed in to redirect_uri + $this->assertArrayHasKey('query', $parts); + $this->assertFalse(isset($parts['fragment'])); + + // assert fragment is in "application/x-www-form-urlencoded" format + parse_str($parts['query'], $query); + $this->assertNotNull($query); + $this->assertArrayHasKey('code', $query); + + // ensure no id_token was saved, since the openid scope wasn't requested + $storage = $server->getStorage('authorization_code'); + $code = $storage->getAuthorizationCode($query['code']); + $this->assertTrue(empty($code['id_token'])); + + // ensure no error was returned + $this->assertFalse(isset($query['error'])); + $this->assertFalse(isset($query['error_description'])); + } + + public function testSuccessfulRequestReturnsStateParameter() + { + $server = $this->getTestServer(array('allow_implicit' => true)); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com', // valid redirect URI + 'response_type' => 'code', + 'state' => 'test', // valid state string (just needs to be passed back to us) + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + + $location = $response->getHttpHeader('Location'); + $parts = parse_url($location); + $this->assertArrayHasKey('query', $parts); + parse_str($parts['query'], $query); + + $this->assertArrayHasKey('state', $query); + $this->assertEquals($query['state'], 'test'); + + // ensure no error was returned + $this->assertFalse(isset($query['error'])); + $this->assertFalse(isset($query['error_description'])); + } + + public function testSuccessfulRequestStripsExtraParameters() + { + $server = $this->getTestServer(array('allow_implicit' => true)); + $request = new Request(array( + 'client_id' => 'Test Client ID', // valid client id + 'redirect_uri' => 'http://adobe.com', // valid redirect URI + 'response_type' => 'code', + 'state' => 'test', // valid state string (just needs to be passed back to us) + 'fake' => 'something', // extra query param + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + $location = $response->getHttpHeader('Location'); + $this->assertNotContains('error', $location); + + $parts = parse_url($location); + $this->assertFalse(isset($parts['fake'])); + $this->assertArrayHasKey('query', $parts); + parse_str($parts['query'], $query); + + $this->assertFalse(isset($parmas['fake'])); + $this->assertArrayHasKey('state', $query); + $this->assertEquals($query['state'], 'test'); + } + + public function testSuccessfulOpenidConnectRequest() + { + $server = $this->getTestServer(array( + 'use_openid_connect' => true, + 'issuer' => 'bojanz', + )); + + $request = new Request(array( + 'client_id' => 'Test Client ID', + 'redirect_uri' => 'http://adobe.com', + 'response_type' => 'code', + 'state' => 'xyz', + 'scope' => 'openid', + )); + $server->handleAuthorizeRequest($request, $response = new Response(), true); + + $this->assertEquals($response->getStatusCode(), 302); + $location = $response->getHttpHeader('Location'); + $parts = parse_url($location); + parse_str($parts['query'], $query); + + $location = $response->getHttpHeader('Location'); + $parts = parse_url($location); + $this->assertArrayHasKey('query', $parts); + $this->assertFalse(isset($parts['fragment'])); + + // assert fragment is in "application/x-www-form-urlencoded" format + parse_str($parts['query'], $query); + $this->assertNotNull($query); + $this->assertArrayHasKey('code', $query); + + // ensure no error was returned + $this->assertFalse(isset($query['error'])); + $this->assertFalse(isset($query['error_description'])); + + // confirm that the id_token has been created. + $storage = $server->getStorage('authorization_code'); + $code = $storage->getAuthorizationCode($query['code']); + $this->assertTrue(!empty($code['id_token'])); + } + + public function testCreateController() + { + $storage = Bootstrap::getInstance()->getMemoryStorage(); + $controller = new AuthorizeController($storage); + } + + private function getTestServer($config = array()) + { + $storage = Bootstrap::getInstance()->getMemoryStorage(); + $server = new Server($storage, $config); + + // Add the two types supported for authorization grant + $server->addGrantType(new AuthorizationCode($storage)); + + return $server; + } +} diff --git a/library/oauth2/test/OAuth2/Controller/ResourceControllerTest.php b/library/oauth2/test/OAuth2/Controller/ResourceControllerTest.php new file mode 100644 index 000000000..ee6d96ff8 --- /dev/null +++ b/library/oauth2/test/OAuth2/Controller/ResourceControllerTest.php @@ -0,0 +1,175 @@ +<?php + +namespace OAuth2\Controller; + +use OAuth2\Storage\Bootstrap; +use OAuth2\Server; +use OAuth2\GrantType\AuthorizationCode; +use OAuth2\Request; +use OAuth2\Response; + +class ResourceControllerTest extends \PHPUnit_Framework_TestCase +{ + public function testNoAccessToken() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertFalse($allow); + + $this->assertEquals($response->getStatusCode(), 401); + $this->assertNull($response->getParameter('error')); + $this->assertNull($response->getParameter('error_description')); + } + + public function testMalformedHeader() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->headers['AUTHORIZATION'] = 'tH1s i5 B0gU5'; + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertFalse($allow); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_request'); + $this->assertEquals($response->getParameter('error_description'), 'Malformed auth header'); + } + + public function testMultipleTokensSubmitted() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->request['access_token'] = 'TEST'; + $request->query['access_token'] = 'TEST'; + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertFalse($allow); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_request'); + $this->assertEquals($response->getParameter('error_description'), 'Only one method may be used to authenticate at a time (Auth header, GET or POST)'); + } + + public function testInvalidRequestMethod() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->server['REQUEST_METHOD'] = 'GET'; + $request->request['access_token'] = 'TEST'; + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertFalse($allow); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_request'); + $this->assertEquals($response->getParameter('error_description'), 'When putting the token in the body, the method must be POST or PUT'); + } + + public function testInvalidContentType() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->server['REQUEST_METHOD'] = 'POST'; + $request->server['CONTENT_TYPE'] = 'application/json'; + $request->request['access_token'] = 'TEST'; + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertFalse($allow); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_request'); + $this->assertEquals($response->getParameter('error_description'), 'The content type for POST requests must be "application/x-www-form-urlencoded"'); + } + + public function testInvalidToken() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->headers['AUTHORIZATION'] = 'Bearer TESTTOKEN'; + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertFalse($allow); + + $this->assertEquals($response->getStatusCode(), 401); + $this->assertEquals($response->getParameter('error'), 'invalid_token'); + $this->assertEquals($response->getParameter('error_description'), 'The access token provided is invalid'); + } + + public function testExpiredToken() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->headers['AUTHORIZATION'] = 'Bearer accesstoken-expired'; + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertFalse($allow); + + $this->assertEquals($response->getStatusCode(), 401); + $this->assertEquals($response->getParameter('error'), 'expired_token'); + $this->assertEquals($response->getParameter('error_description'), 'The access token provided has expired'); + } + + public function testOutOfScopeToken() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->headers['AUTHORIZATION'] = 'Bearer accesstoken-scope'; + $scope = 'outofscope'; + $allow = $server->verifyResourceRequest($request, $response = new Response(), $scope); + $this->assertFalse($allow); + + $this->assertEquals($response->getStatusCode(), 403); + $this->assertEquals($response->getParameter('error'), 'insufficient_scope'); + $this->assertEquals($response->getParameter('error_description'), 'The request requires higher privileges than provided by the access token'); + + // verify the "scope" has been set in the "WWW-Authenticate" header + preg_match('/scope="(.*?)"/', $response->getHttpHeader('WWW-Authenticate'), $matches); + $this->assertEquals(2, count($matches)); + $this->assertEquals($matches[1], 'outofscope'); + } + + public function testMalformedToken() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->headers['AUTHORIZATION'] = 'Bearer accesstoken-malformed'; + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertFalse($allow); + + $this->assertEquals($response->getStatusCode(), 401); + $this->assertEquals($response->getParameter('error'), 'malformed_token'); + $this->assertEquals($response->getParameter('error_description'), 'Malformed token (missing "expires")'); + } + + public function testValidToken() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->headers['AUTHORIZATION'] = 'Bearer accesstoken-scope'; + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertTrue($allow); + } + + public function testValidTokenWithScopeParam() + { + $server = $this->getTestServer(); + $request = Request::createFromGlobals(); + $request->headers['AUTHORIZATION'] = 'Bearer accesstoken-scope'; + $request->query['scope'] = 'testscope'; + $allow = $server->verifyResourceRequest($request, $response = new Response()); + $this->assertTrue($allow); + } + + public function testCreateController() + { + $storage = Bootstrap::getInstance()->getMemoryStorage(); + $tokenType = new \OAuth2\TokenType\Bearer(); + $controller = new ResourceController($tokenType, $storage); + } + + private function getTestServer($config = array()) + { + $storage = Bootstrap::getInstance()->getMemoryStorage(); + $server = new Server($storage, $config); + + // Add the two types supported for authorization grant + $server->addGrantType(new AuthorizationCode($storage)); + + return $server; + } +} diff --git a/library/oauth2/test/OAuth2/Controller/TokenControllerTest.php b/library/oauth2/test/OAuth2/Controller/TokenControllerTest.php new file mode 100644 index 000000000..4a217bd55 --- /dev/null +++ b/library/oauth2/test/OAuth2/Controller/TokenControllerTest.php @@ -0,0 +1,289 @@ +<?php + +namespace OAuth2\Controller; + +use OAuth2\Storage\Bootstrap; +use OAuth2\Server; +use OAuth2\GrantType\AuthorizationCode; +use OAuth2\GrantType\ClientCredentials; +use OAuth2\GrantType\UserCredentials; +use OAuth2\Scope; +use OAuth2\Request\TestRequest; +use OAuth2\Response; + +class TokenControllerTest extends \PHPUnit_Framework_TestCase +{ + public function testNoGrantType() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $server->handleTokenRequest(TestRequest::createPost(), $response = new Response()); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_request'); + $this->assertEquals($response->getParameter('error_description'), 'The grant type was not specified in the request'); + } + + public function testInvalidGrantType() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $request = TestRequest::createPost(array( + 'grant_type' => 'invalid_grant_type', // invalid grant type + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'unsupported_grant_type'); + $this->assertEquals($response->getParameter('error_description'), 'Grant type "invalid_grant_type" not supported'); + } + + public function testNoClientId() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $request = TestRequest::createPost(array( + 'grant_type' => 'authorization_code', // valid grant type + 'code' => 'testcode', + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_client'); + $this->assertEquals($response->getParameter('error_description'), 'Client credentials were not found in the headers or body'); + } + + public function testNoClientSecretWithConfidentialClient() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $request = TestRequest::createPost(array( + 'grant_type' => 'authorization_code', // valid grant type + 'code' => 'testcode', + 'client_id' => 'Test Client ID', // valid client id + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_client'); + $this->assertEquals($response->getParameter('error_description'), 'This client is invalid or must authenticate using a client secret'); + } + + public function testNoClientSecretWithEmptySecret() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $request = TestRequest::createPost(array( + 'grant_type' => 'authorization_code', // valid grant type + 'code' => 'testcode-empty-secret', + 'client_id' => 'Test Client ID Empty Secret', // valid client id + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertEquals($response->getStatusCode(), 200); + } + + public function testInvalidClientId() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $request = TestRequest::createPost(array( + 'grant_type' => 'authorization_code', // valid grant type + 'code' => 'testcode', + 'client_id' => 'Fake Client ID', // invalid client id + 'client_secret' => 'TestSecret', // valid client secret + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_client'); + $this->assertEquals($response->getParameter('error_description'), 'The client credentials are invalid'); + } + + public function testInvalidClientSecret() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $request = TestRequest::createPost(array( + 'grant_type' => 'authorization_code', // valid grant type + 'code' => 'testcode', + 'client_id' => 'Test Client ID', // valid client id + 'client_secret' => 'Fake Client Secret', // invalid client secret + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_client'); + $this->assertEquals($response->getParameter('error_description'), 'The client credentials are invalid'); + } + + public function testValidTokenResponse() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $request = TestRequest::createPost(array( + 'grant_type' => 'authorization_code', // valid grant type + 'client_id' => 'Test Client ID', // valid client id + 'client_secret' => 'TestSecret', // valid client secret + 'code' => 'testcode', // valid authorization code + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertTrue($response instanceof Response); + $this->assertEquals($response->getStatusCode(), 200); + $this->assertNull($response->getParameter('error')); + $this->assertNull($response->getParameter('error_description')); + $this->assertNotNull($response->getParameter('access_token')); + $this->assertNotNull($response->getParameter('expires_in')); + $this->assertNotNull($response->getParameter('token_type')); + } + + public function testValidClientIdScope() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $request = TestRequest::createPost(array( + 'grant_type' => 'authorization_code', // valid grant type + 'code' => 'testcode', + 'client_id' => 'Test Client ID', // valid client id + 'client_secret' => 'TestSecret', // valid client secret + 'scope' => 'clientscope1 clientscope2' + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertEquals($response->getStatusCode(), 200); + $this->assertNull($response->getParameter('error')); + $this->assertNull($response->getParameter('error_description')); + $this->assertEquals('clientscope1 clientscope2', $response->getParameter('scope')); + } + + public function testInvalidClientIdScope() + { + // add the test parameters in memory + $server = $this->getTestServer(); + $request = TestRequest::createPost(array( + 'grant_type' => 'authorization_code', // valid grant type + 'code' => 'testcode-with-scope', + 'client_id' => 'Test Client ID', // valid client id + 'client_secret' => 'TestSecret', // valid client secret + 'scope' => 'clientscope3' + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_scope'); + $this->assertEquals($response->getParameter('error_description'), 'The scope requested is invalid for this request'); + } + + public function testEnforceScope() + { + $storage = Bootstrap::getInstance()->getMemoryStorage(); + $server = new Server($storage); + $server->addGrantType(new ClientCredentials($storage)); + + $scope = new Scope(array( + 'default_scope' => false, + 'supported_scopes' => array('testscope') + )); + $server->setScopeUtil($scope); + + $request = TestRequest::createPost(array( + 'grant_type' => 'client_credentials', // valid grant type + 'client_id' => 'Test Client ID', // valid client id + 'client_secret' => 'TestSecret', // valid client secret + )); + $response = $server->handleTokenRequest($request); + + $this->assertEquals($response->getStatusCode(), 400); + $this->assertEquals($response->getParameter('error'), 'invalid_scope'); + $this->assertEquals($response->getParameter('error_description'), 'This application requires you specify a scope parameter'); + } + + public function testCanReceiveAccessTokenUsingPasswordGrantTypeWithoutClientSecret() + { + // add the test parameters in memory + $storage = Bootstrap::getInstance()->getMemoryStorage(); + $server = new Server($storage); + $server->addGrantType(new UserCredentials($storage)); + + $request = TestRequest::createPost(array( + 'grant_type' => 'password', // valid grant type + 'client_id' => 'Test Client ID For Password Grant', // valid client id + 'username' => 'johndoe', // valid username + 'password' => 'password', // valid password for username + )); + $server->handleTokenRequest($request, $response = new Response()); + + $this->assertTrue($response instanceof Response); + $this->assertEquals(200, $response->getStatusCode(), var_export($response, 1)); + $this->assertNull($response->getParameter('error')); + $this->assertNull($response->getParameter('error_description')); + $this->assertNotNull($response->getParameter('access_token')); + $this->assertNotNull($response->getParameter('expires_in')); + $this->assertNotNull($response->getParameter('token_type')); + } + + public function testInvalidTokenTypeHintForRevoke() + { + $server = $this->getTestServer(); + + $request = TestRequest::createPost(array( + 'token_type_hint' => 'foo', + 'token' => 'sometoken' + )); + + $server->handleRevokeRequest($request, $response = new Response()); + + $this->assertTrue($response instanceof Response); + $this->assertEquals(400, $response->getStatusCode(), var_export($response, 1)); + $this->assertEquals($response->getParameter('error'), 'invalid_request'); + $this->assertEquals($response->getParameter('error_description'), 'Token type hint must be either \'access_token\' or \'refresh_token\''); + } + + public function testMissingTokenForRevoke() + { + $server = $this->getTestServer(); + + $request = TestRequest::createPost(array( + 'token_type_hint' => 'access_token' + )); + + $server->handleRevokeRequest($request, $response = new Response()); + $this->assertTrue($response instanceof Response); + $this->assertEquals(400, $response->getStatusCode(), var_export($response, 1)); + $this->assertEquals($response->getParameter('error'), 'invalid_request'); + $this->assertEquals($response->getParameter('error_description'), 'Missing token parameter to revoke'); + } + + public function testInvalidRequestMethodForRevoke() + { + $server = $this->getTestServer(); + + $request = new TestRequest(); + $request->setQuery(array( + 'token_type_hint' => 'access_token' + )); + + $server->handleRevokeRequest($request, $response = new Response()); + $this->assertTrue($response instanceof Response); + $this->assertEquals(405, $response->getStatusCode(), var_export($response, 1)); + $this->assertEquals($response->getParameter('error'), 'invalid_request'); + $this->assertEquals($response->getParameter('error_description'), 'The request method must be POST when revoking an access token'); + } + + public function testCreateController() + { + $storage = Bootstrap::getInstance()->getMemoryStorage(); + $accessToken = new \OAuth2\ResponseType\AccessToken($storage); + $controller = new TokenController($accessToken, $storage); + } + + private function getTestServer() + { + $storage = Bootstrap::getInstance()->getMemoryStorage(); + $server = new Server($storage); + $server->addGrantType(new AuthorizationCode($storage)); + + return $server; + } +} |