verifyAccessToken() with a missing token */ public function testVerifyAccessTokenWithNoParam() { $mockStorage = $this->getMock('IOAuth2Storage'); $this->fixture = new OAuth2($mockStorage); $scope = null; $this->setExpectedException('OAuth2AuthenticateException'); $this->fixture->verifyAccessToken('', $scope); } /** * Tests OAuth2->verifyAccessToken() with a invalid token */ public function testVerifyAccessTokenInvalidToken() { // Set up the mock storage to say this token does not exist $mockStorage = $this->getMock('IOAuth2Storage'); $mockStorage->expects($this->once()) ->method('getAccessToken') ->will($this->returnValue(false)); $this->fixture = new OAuth2($mockStorage); $scope = null; $this->setExpectedException('OAuth2AuthenticateException'); $this->fixture->verifyAccessToken($this->tokenId, $scope); } /** * Tests OAuth2->verifyAccessToken() with a malformed token * * @dataProvider generateMalformedTokens */ public function testVerifyAccessTokenMalformedToken($token) { // Set up the mock storage to say this token does not exist $mockStorage = $this->getMock('IOAuth2Storage'); $mockStorage->expects($this->once()) ->method('getAccessToken') ->will($this->returnValue($token)); $this->fixture = new OAuth2($mockStorage); $scope = null; $this->setExpectedException('OAuth2AuthenticateException'); $this->fixture->verifyAccessToken($this->tokenId, $scope); } /** * Tests OAuth2->verifyAccessToken() with different expiry dates * * @dataProvider generateExpiryTokens */ public function testVerifyAccessTokenCheckExpiry($token, $expectedToPass) { // Set up the mock storage to say this token does not exist $mockStorage = $this->getMock('IOAuth2Storage'); $mockStorage->expects($this->once()) ->method('getAccessToken') ->will($this->returnValue($token)); $this->fixture = new OAuth2($mockStorage); $scope = null; // When valid, we just want any sort of token if ($expectedToPass) { $actual = $this->fixture->verifyAccessToken($this->tokenId, $scope); $this->assertNotEmpty($actual, "verifyAccessToken() was expected to PASS, but it failed"); $this->assertInternalType('array', $actual); } else { $this->setExpectedException('OAuth2AuthenticateException'); $this->fixture->verifyAccessToken($this->tokenId, $scope); } } /** * Tests OAuth2->verifyAccessToken() with different scopes * * @dataProvider generateScopes */ public function testVerifyAccessTokenCheckScope($scopeRequired, $token, $expectedToPass) { // Set up the mock storage to say this token does not exist $mockStorage = $this->getMock('IOAuth2Storage'); $mockStorage->expects($this->once()) ->method('getAccessToken') ->will($this->returnValue($token)); $this->fixture = new OAuth2($mockStorage); // When valid, we just want any sort of token if ($expectedToPass) { $actual = $this->fixture->verifyAccessToken($this->tokenId, $scopeRequired); $this->assertNotEmpty($actual, "verifyAccessToken() was expected to PASS, but it failed"); $this->assertInternalType('array', $actual); } else { $this->setExpectedException('OAuth2AuthenticateException'); $this->fixture->verifyAccessToken($this->tokenId, $scopeRequired); } } /** * Tests OAuth2->grantAccessToken() for missing data * * @dataProvider generateEmptyDataForGrant */ public function testGrantAccessTokenMissingData($inputData, $authHeaders) { $mockStorage = $this->getMock('IOAuth2Storage'); $this->fixture = new OAuth2($mockStorage); $this->setExpectedException('OAuth2ServerException'); $this->fixture->grantAccessToken($inputData, $authHeaders); } /** * Tests OAuth2->grantAccessToken() * * Tests the different ways client credentials can be provided. */ public function testGrantAccessTokenCheckClientCredentials() { $mockStorage = $this->getMock('IOAuth2Storage'); $mockStorage->expects($this->any()) ->method('checkClientCredentials') ->will($this->returnValue(TRUE)); // Always return true for any combination of user/pass $this->fixture = new OAuth2($mockStorage); $inputData = array('grant_type' => OAuth2::GRANT_TYPE_AUTH_CODE); $authHeaders = array(); // First, confirm that an non-client related error is thrown: try { $this->fixture->grantAccessToken($inputData, $authHeaders); $this->fail('The expected exception OAuth2ServerException was not thrown'); } catch ( OAuth2ServerException $e ) { $this->assertEquals(OAuth2::ERROR_INVALID_CLIENT, $e->getMessage()); } // Confirm Auth header $authHeaders = array('PHP_AUTH_USER' => 'dev-abc', 'PHP_AUTH_PW' => 'pass'); $inputData = array('grant_type' => OAuth2::GRANT_TYPE_AUTH_CODE, 'client_id' => 'dev-abc'); // When using auth, client_id must match try { $this->fixture->grantAccessToken($inputData, $authHeaders); $this->fail('The expected exception OAuth2ServerException was not thrown'); } catch ( OAuth2ServerException $e ) { $this->assertNotEquals(OAuth2::ERROR_INVALID_CLIENT, $e->getMessage()); } // Confirm GET/POST $authHeaders = array(); $inputData = array('grant_type' => OAuth2::GRANT_TYPE_AUTH_CODE, 'client_id' => 'dev-abc', 'client_secret' => 'foo'); // When using auth, client_id must match try { $this->fixture->grantAccessToken($inputData, $authHeaders); $this->fail('The expected exception OAuth2ServerException was not thrown'); } catch ( OAuth2ServerException $e ) { $this->assertNotEquals(OAuth2::ERROR_INVALID_CLIENT, $e->getMessage()); } } /** * Tests OAuth2->grantAccessToken() with Auth code grant * */ public function testGrantAccessTokenWithGrantAuthCodeMandatoryParams() { $mockStorage = $this->createBaseMock('IOAuth2GrantCode'); $inputData = array('grant_type' => OAuth2::GRANT_TYPE_AUTH_CODE, 'client_id' => 'a', 'client_secret' => 'b'); $fakeAuthCode = array('client_id' => $inputData['client_id'], 'redirect_uri' => '/foo', 'expires' => time() + 60); $fakeAccessToken = array('access_token' => 'abcde'); // Ensure redirect URI and auth-code is mandatory try { $this->fixture = new OAuth2($mockStorage); $this->fixture->setVariable(OAuth2::CONFIG_ENFORCE_INPUT_REDIRECT, true); // Only required when this is set $this->fixture->grantAccessToken($inputData + array('code' => 'foo'), array()); $this->fail('The expected exception OAuth2ServerException was not thrown'); } catch ( OAuth2ServerException $e ) { $this->assertEquals(OAuth2::ERROR_INVALID_REQUEST, $e->getMessage()); } try { $this->fixture = new OAuth2($mockStorage); $this->fixture->grantAccessToken($inputData + array('redirect_uri' => 'foo'), array()); $this->fail('The expected exception OAuth2ServerException was not thrown'); } catch ( OAuth2ServerException $e ) { $this->assertEquals(OAuth2::ERROR_INVALID_REQUEST, $e->getMessage()); } } /** * Tests OAuth2->grantAccessToken() with Auth code grant * */ public function testGrantAccessTokenWithGrantAuthCodeNoToken() { $mockStorage = $this->createBaseMock('IOAuth2GrantCode'); $inputData = array('grant_type' => OAuth2::GRANT_TYPE_AUTH_CODE, 'client_id' => 'a', 'client_secret' => 'b', 'redirect_uri' => 'foo', 'code'=> 'foo'); // Ensure missing auth code raises an error try { $this->fixture = new OAuth2($mockStorage); $this->fixture->grantAccessToken($inputData + array(), array()); $this->fail('The expected exception OAuth2ServerException was not thrown'); } catch ( OAuth2ServerException $e ) { $this->assertEquals(OAuth2::ERROR_INVALID_GRANT, $e->getMessage()); } } /** * Tests OAuth2->grantAccessToken() with checks the redirect URI * */ public function testGrantAccessTokenWithGrantAuthCodeRedirectChecked() { $inputData = array('redirect_uri' => 'http://www.crossdomain.com/my/subdir', 'grant_type' => OAuth2::GRANT_TYPE_AUTH_CODE, 'client_id' => 'my_little_app', 'client_secret' => 'b', 'code'=> 'foo'); $storedToken = array('redirect_uri' => 'http://www.example.com', 'client_id' => 'my_little_app', 'expires' => time() + 60); $mockStorage = $this->createBaseMock('IOAuth2GrantCode'); $mockStorage->expects($this->any()) ->method('getAuthCode') ->will($this->returnValue($storedToken)); // Ensure that the redirect_uri is checked try { $this->fixture = new OAuth2($mockStorage); $this->fixture->grantAccessToken($inputData, array()); $this->fail('The expected exception OAuth2ServerException was not thrown'); } catch ( OAuth2ServerException $e ) { $this->assertEquals(OAuth2::ERROR_REDIRECT_URI_MISMATCH, $e->getMessage()); } } /** * Tests OAuth2->grantAccessToken() with checks the client ID is matched * */ public function testGrantAccessTokenWithGrantAuthCodeClientIdChecked() { $inputData = array('client_id' => 'another_app', 'grant_type' => OAuth2::GRANT_TYPE_AUTH_CODE, 'redirect_uri' => 'http://www.example.com/my/subdir', 'client_secret' => 'b', 'code'=> 'foo'); $storedToken = array('client_id' => 'my_little_app', 'redirect_uri' => 'http://www.example.com', 'expires' => time() + 60); $mockStorage = $this->createBaseMock('IOAuth2GrantCode'); $mockStorage->expects($this->any()) ->method('getAuthCode') ->will($this->returnValue($storedToken)); // Ensure the client ID is checked try { $this->fixture = new OAuth2($mockStorage); $this->fixture->grantAccessToken($inputData, array()); $this->fail('The expected exception OAuth2ServerException was not thrown'); } catch ( OAuth2ServerException $e ) { $this->assertEquals(OAuth2::ERROR_INVALID_GRANT, $e->getMessage()); } } /** * Tests OAuth2->grantAccessToken() with implicit * */ public function testGrantAccessTokenWithGrantImplicit() { $this->markTestIncomplete ( "grantAccessToken test not implemented" ); $this->fixture->grantAccessToken(/* parameters */); } /** * Tests OAuth2->grantAccessToken() with user credentials * */ public function testGrantAccessTokenWithGrantUser() { $this->markTestIncomplete ( "grantAccessToken test not implemented" ); $this->fixture->grantAccessToken(/* parameters */); } /** * Tests OAuth2->grantAccessToken() with client credentials * */ public function testGrantAccessTokenWithGrantClient() { $this->markTestIncomplete ( "grantAccessToken test not implemented" ); $this->fixture->grantAccessToken(/* parameters */); } /** * Tests OAuth2->grantAccessToken() with refresh token * */ public function testGrantAccessTokenWithGrantRefresh() { $this->markTestIncomplete ( "grantAccessToken test not implemented" ); $this->fixture->grantAccessToken(/* parameters */); } /** * Tests OAuth2->grantAccessToken() with extension * */ public function testGrantAccessTokenWithGrantExtension() { $this->markTestIncomplete ( "grantAccessToken test not implemented" ); $this->fixture->grantAccessToken(/* parameters */); } /** * Tests OAuth2->getAuthorizeParams() */ public function testGetAuthorizeParams() { // TODO Auto-generated OAuth2Test->testGetAuthorizeParams() $this->markTestIncomplete ( "getAuthorizeParams test not implemented" ); $this->fixture->getAuthorizeParams(/* parameters */); } /** * Tests OAuth2->finishClientAuthorization() */ public function testFinishClientAuthorization() { // TODO Auto-generated OAuth2Test->testFinishClientAuthorization() $this->markTestIncomplete ( "finishClientAuthorization test not implemented" ); $this->fixture->finishClientAuthorization(/* parameters */); } // Utility methods /** * * @param string $interfaceName */ protected function createBaseMock($interfaceName) { $mockStorage = $this->getMock($interfaceName); $mockStorage->expects($this->any()) ->method('checkClientCredentials') ->will($this->returnValue(TRUE)); // Always return true for any combination of user/pass $mockStorage->expects($this->any()) ->method('checkRestrictedGrantType') ->will($this->returnValue(TRUE)); // Always return true for any combination of user/pass return $mockStorage; } // Data Providers below: /** * Dataprovider for testVerifyAccessTokenMalformedToken(). * * Produces malformed access tokens */ public function generateMalformedTokens() { return array( array(array()), // an empty array as a token array(array('expires' => 5)), // missing client_id array(array('client_id' => 6)), // missing expires array(array('something' => 6)), // missing both 'expires' and 'client_id' ); } /** * Dataprovider for testVerifyAccessTokenCheckExpiry(). * * Produces malformed access tokens */ public function generateExpiryTokens() { return array( array(array('client_id' => 'blah', 'expires' => time() - 30), FALSE), // 30 seconds ago should fail array(array('client_id' => 'blah', 'expires' => time() - 1), FALSE), // now-ish should fail array(array('client_id' => 'blah', 'expires' => 0), FALSE), // 1970 should fail array(array('client_id' => 'blah', 'expires' => time() + 30), TRUE), // 30 seconds in the future should be valid array(array('client_id' => 'blah', 'expires' => time() + 86400), TRUE), // 1 day in the future should be valid array(array('client_id' => 'blah', 'expires' => time() + (365 * 86400)), TRUE), // 1 year should be valid array(array('client_id' => 'blah', 'expires' => time() + (10 * 365 * 86400)), TRUE), // 10 years should be valid ); } /** * Dataprovider for testVerifyAccessTokenCheckExpiry(). * * Produces malformed access tokens */ public function generateScopes() { $baseToken = array('client_id' => 'blah', 'expires' => time() + 60); return array( array(null, $baseToken + array(), TRUE), // missing scope is valif array(null, $baseToken + array('scope' => null), TRUE), // null scope is valid array('', $baseToken + array('scope' => ''), TRUE), // empty scope is valid array('read', $baseToken + array('scope' => 'read'), TRUE), // exact same scope is valid array('read', $baseToken + array('scope' => ' read '), TRUE), // exact same scope is valid array(' read ', $baseToken + array('scope' => 'read'), TRUE), // exact same scope is valid array('read', $baseToken + array('scope' => 'read write delete'), TRUE), // contains scope array('read', $baseToken + array('scope' => 'write read delete'), TRUE), // contains scope array('read', $baseToken + array('scope' => 'delete write read'), TRUE), // contains scope // Invalid combinations array('read', $baseToken + array('scope' => 'write'), FALSE), array('read', $baseToken + array('scope' => 'apple banana'), FALSE), array('read', $baseToken + array('scope' => 'apple read-write'), FALSE), array('read', $baseToken + array('scope' => 'apple read,write'), FALSE), array('read', $baseToken + array('scope' => null), FALSE), array('read', $baseToken + array('scope' => ''), FALSE), ); } /** * Provider for OAuth2->grantAccessToken() */ public function generateEmptyDataForGrant() { return array( array( array(), array() ), array( array(), array('grant_type' => OAuth2::GRANT_TYPE_AUTH_CODE) // grant_type in auth headers should be ignored ), array( array('not_grant_type' => 5), array() ), ); } }