/** * Execute operations before OAuth2 Server sends a token response. * * @param \OAuth2Server|NULL $server * @param \OAuth2\Request $request * @param \OAuth2\Response $response */ function hook_oauth2_server_token($server, \OAuth2\Request $request, \OAuth2\Response $response) { // Example: if the response is not successful, log a message. if ($response->getStatusCode() != 200) { watchdog('mymodule', 'Failed token response from server @server: @code @body', array('@server' => $server ? $server->name : NULL, '@code' => $response->getStatusCode(), '@body' => $response->getResponseBody())); } }
/** * Constructor. * @param Response $response * @param \Exception $previous The previous exception used for the exception chaining. */ public function __construct(Response $response, \Exception $previous = null) { if ((int) $response->getStatusCode() == 401) { $errorCode = $response->getParameter('error', 'required_token'); $message = $response->getParameter('error_description', 'An Access Token is required.'); } else { $errorCode = $response->getParameter('error', 'unknown'); $message = $response->getParameter('error_description', $response->getStatusText()); } $this->errorCode = $errorCode; $this->errorUri = $response->getParameter('error_uri'); return parent::__construct($response->getStatusCode(), $message, 0, $previous); }
public function __construct(\OAuth2\Response $response) { $this->response = $response; $this->code = $response->getStatusCode(); $this->description = $response->getStatusText(); $this->message = $response->getResponseBody(); }
public function testValidCredentialsInvalidScope() { $server = $this->getTestServer(); $request = TestRequest::createPost(array('grant_type' => 'password', 'client_id' => 'Test Client ID', 'client_secret' => 'TestSecret', 'username' => 'test-username', 'password' => 'testpass', 'scope' => 'invalid-scope')); $token = $server->grantAccessToken($request, $response = new Response()); $this->assertEquals($response->getStatusCode(), 400); $this->assertEquals($response->getParameter('error'), 'invalid_scope'); $this->assertEquals($response->getParameter('error_description'), 'An unsupported scope was requested'); }
/** * Convert the OAuth2 response to a \Zend\Http\Response * * @param $response OAuth2Response * @return \Zend\Http\Response */ private function setHttpResponse(OAuth2Response $response) { $httpResponse = $this->getResponse(); $httpResponse->setStatusCode($response->getStatusCode()); $headers = $httpResponse->getHeaders(); $headers->addHeaders($response->getHttpHeaders()); $headers->addHeaderLine('Content-type', 'application/json'); $httpResponse->setContent($response->getResponseBody()); return $httpResponse; }
public function testInvalidContentType() { $bearer = new Bearer(); $request = TestRequest::createPost(array('access_token' => 'ThisIsMyAccessToken')); $request->server['CONTENT_TYPE'] = 'application/json; charset=UTF-8'; $param = $bearer->getAccessTokenParameter($request, $response = new Response()); $this->assertNull($param); $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"'); }
/** * Takes an OAuth2 response and converts it to JSON output via Tonis\Http\Response. * * @param Response $oauthResponse * @param ResponseInterface $psrResponse * @return ResponseInterface */ public static function convertResponseToPsr7(Response $oauthResponse, ResponseInterface $psrResponse) { $psrResponse = $psrResponse->withStatus($oauthResponse->getStatusCode()); foreach ($oauthResponse->getHttpHeaders() as $header => $value) { $psrResponse = $psrResponse->withHeader($header, $value); } if (!empty($oauthResponse->getParameters())) { $psrResponse = $psrResponse->withHeader('Content-Type', 'application/json'); $psrResponse->getBody()->write(json_encode($oauthResponse->getParameters())); } return $psrResponse; }
/** * Copies values from the given Oauth2\Response to a PSR-7 Http Response. * * @param OAuth2\Response $oauth2Response The OAuth2 server response. * * @return \Psr\Http\Message\ResponseInterface */ public static final function fromOauth2(OAuth2\Response $oauth2Response) { $headers = []; foreach ($oauth2Response->getHttpHeaders() as $key => $value) { $headers[$key] = explode(', ', $value); } $stream = fopen('php://temp', 'r+'); if (!empty($oauth2Response->getParameters())) { fwrite($stream, $oauth2Response->getResponseBody()); rewind($stream); } return new Response(new Stream($stream), $oauth2Response->getStatusCode(), $headers); }
public function testSuccessfulRequestStripsExtraParameters() { $server = $this->getTestServer(array('allow_implicit' => true)); $request = new Request(array('client_id' => 'Test Client ID', 'redirect_uri' => 'http://adobe.com?fake=something', 'response_type' => 'token', 'state' => 'test', 'fake' => 'something')); $server->handleAuthorizeRequest($request, $response = new Response(), true); $this->assertEquals($response->getStatusCode(), 302); $this->assertNull($response->getParameter('error')); $this->assertNull($response->getParameter('error_description')); $location = $response->getHttpHeader('Location'); $parts = parse_url($location); $this->assertFalse(isset($parts['fake'])); $this->assertArrayHasKey('fragment', $parts); parse_str($parts['fragment'], $params); $this->assertFalse(isset($parmas['fake'])); $this->assertArrayHasKey('state', $params); $this->assertEquals($params['state'], 'test'); }
private function extractTokenDataFromResponse(Response $response) { $this->assertEquals($response->getStatusCode(), 302); $location = $response->getHttpHeader('Location'); $this->assertNotContains('error', $location); $parts = parse_url($location); $this->assertArrayHasKey('fragment', $parts); $this->assertFalse(isset($parts['query'])); parse_str($parts['fragment'], $params); $this->assertNotNull($params); $this->assertArrayHasKey('id_token', $params); $this->assertArrayNotHasKey('access_token', $params); list($headb64, $payloadb64, $signature) = explode('.', $params['id_token']); $jwt = new Jwt(); $header = json_decode($jwt->urlSafeB64Decode($headb64), true); $payload = json_decode($jwt->urlSafeB64Decode($payloadb64), true); return array($header, $payload, $signature); }
public function testRequestOverride() { $request = new TestRequest(); $server = $this->getTestServer(); // Smoke test for override request class // $server->handleTokenRequest($request, $response = new Response()); // $this->assertInstanceOf('Response', $response); // $server->handleAuthorizeRequest($request, $response = new Response(), true); // $this->assertInstanceOf('Response', $response); // $response = $server->verifyResourceRequest($request, $response = new Response()); // $this->assertTrue(is_bool($response)); /*** make some valid requests ***/ // Valid Token Request $request->setPost(array('grant_type' => 'authorization_code', 'client_id' => 'Test Client ID', 'client_secret' => 'TestSecret', 'code' => 'testcode')); $server->handleTokenRequest($request, $response = new Response()); $this->assertEquals($response->getStatusCode(), 200); $this->assertNull($response->getParameter('error')); $this->assertNotNUll($response->getParameter('access_token')); }
public function testHandleAuthorizeRequest() { // add the test parameters in memory $server = $this->getTestServer(array('allow_implicit' => true)); $request = new Request(array('response_type' => 'token id_token', 'redirect_uri' => 'http://adobe.com', 'client_id' => 'Test Client ID', 'scope' => 'openid', 'state' => 'test', 'nonce' => 'test')); $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->assertArrayHasKey('fragment', $parts); $this->assertFalse(isset($parts['query'])); // assert fragment is in "application/x-www-form-urlencoded" format parse_str($parts['fragment'], $params); $this->assertNotNull($params); $this->assertArrayHasKey('id_token', $params); $this->assertArrayHasKey('access_token', $params); $this->validateIdToken($params['id_token']); }
public function testHandleAuthorizeRequest() { // add the test parameters in memory $server = $this->getTestServer(); $request = new Request(array('response_type' => 'code id_token', 'redirect_uri' => 'http://adobe.com', 'client_id' => 'Test Client ID', 'scope' => 'openid', 'state' => 'test', 'nonce' => 'test')); $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->assertArrayHasKey('query', $parts); // assert fragment is in "application/x-www-form-urlencoded" format parse_str($parts['query'], $params); $this->assertNotNull($params); $this->assertArrayHasKey('id_token', $params); $this->assertArrayHasKey('code', $params); // validate ID Token $parts = explode('.', $params['id_token']); foreach ($parts as &$part) { // Each part is a base64url encoded json string. $part = str_replace(array('-', '_'), array('+', '/'), $part); $part = base64_decode($part); $part = json_decode($part, true); } list($header, $claims, $signature) = $parts; $this->assertArrayHasKey('iss', $claims); $this->assertArrayHasKey('sub', $claims); $this->assertArrayHasKey('aud', $claims); $this->assertArrayHasKey('iat', $claims); $this->assertArrayHasKey('exp', $claims); $this->assertArrayHasKey('auth_time', $claims); $this->assertArrayHasKey('nonce', $claims); // only exists if an access token was granted along with the id_token $this->assertArrayNotHasKey('at_hash', $claims); $this->assertEquals($claims['iss'], 'test'); $this->assertEquals($claims['aud'], 'Test Client ID'); $this->assertEquals($claims['nonce'], 'test'); $duration = $claims['exp'] - $claims['iat']; $this->assertEquals($duration, 3600); }
public function testGrantCodeAccessTokenOnNewCode() { $request = TestRequest::createPost(array('grant_type' => 'device_code', 'client_id' => 'test_client_id')); $this->server->handleDeviceRequest($request, $response = new Response()); $this->assertNotNull($response->getParameter('code')); $deviceCodeResponse = $response; // Get access token when user_id is null $request = TestRequest::createPost(array('grant_type' => 'device_token', 'client_id' => 'test_client_id', 'code' => $deviceCodeResponse->getParameter('code'))); $this->server->handleDeviceRequest($request, $response = new Response()); $this->assertEquals($response->getStatusCode(), 400); $this->assertArrayHasKey('error', $response->getParameters()); $this->assertEquals('authorization_pending', $response->getParameter('error')); // Update user_id and verify response $deviceStorage = $this->server->getStorage('device_code'); $code = $deviceStorage->getDeviceCode($deviceCodeResponse->getParameter('code'), 'test_client_id'); $deviceStorage->setDeviceCode($code['device_code'], $code['user_code'], $code['client_id'], 1, $code['expires'], $code['scope']); $request = TestRequest::createPost(array('grant_type' => 'device_token', 'client_id' => 'test_client_id', 'code' => $deviceCodeResponse->getParameter('code'))); $this->server->handleDeviceRequest($request, $response = new Response()); $this->assertEquals($response->getStatusCode(), 200); $this->assertArrayHasKey('access_token', $response->getParameters()); //ensure device code was deleted $code = $deviceStorage->getDeviceCode($deviceCodeResponse->getParameter('code'), 'test_client_id'); $this->assertFalse($code); }
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', 'client_id' => 'Test Client ID For Password Grant', 'username' => 'johndoe', 'password' => 'password')); $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 testJtiReplayAttack() { $server = $this->getTestServer(); $request = TestRequest::createPost(array('grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $this->getJWT(99999999900, null, '*****@*****.**', 'Test Client ID', 'totally_new_jti'))); $token = $server->grantAccessToken($request, $response = new Response()); $this->assertNotNull($token); $this->assertArrayHasKey('access_token', $token); //Replay the same request $token = $server->grantAccessToken($request, $response = new Response()); $this->assertEquals($response->getStatusCode(), 400); $this->assertEquals($response->getParameter('error'), 'invalid_grant'); $this->assertEquals($response->getParameter('error_description'), 'JSON Token Identifier (jti) has already been used'); }
public function testValidClientDifferentCode() { $server = $this->getTestServer(); $request = TestRequest::createPost(array('grant_type' => 'authorization_code', 'client_id' => 'Test Some Other Client', 'client_secret' => 'TestSecret3', 'code' => 'testcode')); $token = $server->grantAccessToken($request, $response = new Response()); $this->assertEquals($response->getStatusCode(), 400); $this->assertEquals($response->getParameter('error'), 'invalid_grant'); $this->assertEquals($response->getParameter('error_description'), 'authorization_code doesn\'t exist or is invalid for the client'); }
/** * @param Response $response */ public function __construct(Response $response) { $this->setStatusCode($response->getStatusCode()); $this->getHeaders()->addHeader(new GenericHeader('Content-type', 'application/json'))->addHeaders($response->getHttpHeaders()); $this->setContent($response->getResponseBody('json')); }
private function buildResponse($format, HttpResponse $httpResponse, OAuthResponse $oauthResponse) { $httpResponse->setVersion($oauthResponse->version); $httpResponse->setStatusCode($oauthResponse->getStatusCode()); $headers = $httpResponse->getHeaders(); foreach ($oauthResponse->getHttpHeaders() as $name => $value) { $headers->addHeaderLine(sprintf('%s: %s', $name, $value)); } switch ($format) { case 'json': $headers->addHeaderLine('Content-Type: application/json'); $httpResponse->setContent(json_encode($oauthResponse->getParameters())); break; case 'xml': $headers->addHeaderLine('Content-Type: text/xml'); $xml = new SimpleXMLElement('<response/>'); foreach ($oauthResponse->getParameters() as $key => $param) { $xml->addChild($key, $param); } $httpResponse->setContent($xml->asXML()); break; default: throw new RuntimeException('Invalid format provided: ' . $format); } return $httpResponse; }
public function testInvalidClientIdScope() { // add the test parameters in memory $server = $this->getTestServer(); $request = TestRequest::createPost(array('grant_type' => 'authorization_code', 'code' => 'testcode', 'client_id' => 'Test Client ID', 'client_secret' => 'TestSecret', 'scope' => 'clientscope3 scope1')); $server->handleTokenRequest($request, $response = new Response()); $this->assertEquals($response->getStatusCode(), 400); $this->assertEquals($response->getParameter('error'), 'invalid_scope'); $this->assertEquals($response->getParameter('error_description'), 'An unsupported scope was requested'); }
public function testValidJwtInvalidScope() { $server = $this->getTestServer(); $request = TestRequest::createPost(array('grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $this->getJWT(null, null, null, 'Test Client ID', 'invalid-scope'))); $token = $server->grantAccessToken($request, $response = new Response()); $this->assertEquals($response->getStatusCode(), 400); $this->assertEquals($response->getParameter('error'), 'invalid_scope'); $this->assertEquals($response->getParameter('error_description'), 'An unsupported scope was requested'); }
public function testAddingResponseType() { $storage = $this->getMock('OAuth2\\Storage\\Memory'); $storage->expects($this->any())->method('getClientDetails')->will($this->returnValue(array('client_id' => 'some_client'))); $storage->expects($this->any())->method('checkRestrictedGrantType')->will($this->returnValue(true)); // add with the "code" key explicitly set $codeType = new AuthorizationCode($storage); $server = new Server(); $server->addStorage($storage); $server->addResponseType($codeType); $request = new Request(array('response_type' => 'code', 'client_id' => 'some_client', 'redirect_uri' => 'http://example.com', 'state' => 'xyx')); $server->handleAuthorizeRequest($request, $response = new Response(), true); // the response is successful $this->assertEquals($response->getStatusCode(), 302); $parts = parse_url($response->getHttpHeader('Location')); parse_str($parts['query'], $query); $this->assertTrue(isset($query['code'])); $this->assertFalse(isset($query['error'])); // add with the "code" key not set $codeType = new AuthorizationCode($storage); $server = new Server(array($storage), array(), array(), array($codeType)); $request = new Request(array('response_type' => 'code', 'client_id' => 'some_client', 'redirect_uri' => 'http://example.com', 'state' => 'xyx')); $server->handleAuthorizeRequest($request, $response = new Response(), true); // the response is successful $this->assertEquals($response->getStatusCode(), 302); $parts = parse_url($response->getHttpHeader('Location')); parse_str($parts['query'], $query); $this->assertTrue(isset($query['code'])); $this->assertFalse(isset($query['error'])); }
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'), 'invalid_token'); $this->assertEquals($response->getParameter('error_description'), 'Malformed token (missing "expires")'); }
public function testNoSecretWithConfidentialClient() { $server = $this->getTestServer(); $request = TestRequest::createPost(array('grant_type' => 'password', 'client_id' => 'Test Client ID', 'username' => 'test-username', 'password' => 'testpass')); $token = $server->grantAccessToken($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 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 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'])); }