aboutsummaryrefslogtreecommitdiffstats
path: root/library/oauth2/test/OAuth2/Controller
diff options
context:
space:
mode:
authorzotlabs <mike@macgirvin.com>2016-10-07 14:11:24 -0700
committerzotlabs <mike@macgirvin.com>2016-10-07 14:11:24 -0700
commit10863a5949cc59771424cb809af5c9f279f78a58 (patch)
tree7a86223b830c1ae784bd4557bbefee9f60169542 /library/oauth2/test/OAuth2/Controller
parentbf02e0428347350126abdd1726aa3e58c9ed63bb (diff)
downloadvolse-hubzilla-10863a5949cc59771424cb809af5c9f279f78a58.tar.gz
volse-hubzilla-10863a5949cc59771424cb809af5c9f279f78a58.tar.bz2
volse-hubzilla-10863a5949cc59771424cb809af5c9f279f78a58.zip
add oauth2/oidc lib
Diffstat (limited to 'library/oauth2/test/OAuth2/Controller')
-rw-r--r--library/oauth2/test/OAuth2/Controller/AuthorizeControllerTest.php492
-rw-r--r--library/oauth2/test/OAuth2/Controller/ResourceControllerTest.php175
-rw-r--r--library/oauth2/test/OAuth2/Controller/TokenControllerTest.php289
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;
+ }
+}