public function handle(RequestInterface $request, ResponseInterface $response, FilterChainInterface $filterChain) { $authorization = $request->getHeader('Authorization'); if (!empty($authorization)) { $parts = explode(' ', $authorization, 2); $type = isset($parts[0]) ? $parts[0] : null; $data = isset($parts[1]) ? $parts[1] : null; if ($type == 'OAuth' && !empty($data)) { $params = Authentication::decodeParameters($data); $params = array_map(array('\\PSX\\Oauth', 'urlDecode'), $params); // realm is not used in the base string unset($params['realm']); if (!isset($params['oauth_consumer_key'])) { throw new BadRequestException('Consumer key not set'); } if (!isset($params['oauth_token'])) { throw new BadRequestException('Token not set'); } if (!isset($params['oauth_signature_method'])) { throw new BadRequestException('Signature method not set'); } if (!isset($params['oauth_signature'])) { throw new BadRequestException('Signature not set'); } $consumer = call_user_func_array($this->consumerCallback, array($params['oauth_consumer_key'], $params['oauth_token'])); if ($consumer instanceof Consumer) { $signature = Oauth::getSignature($params['oauth_signature_method']); $method = $request->getMethod(); $url = $request->getUri(); $params = array_merge($params, $request->getUri()->getParameters()); if (strpos($request->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) { $body = (string) $request->getBody(); $data = array(); parse_str($body, $data); $params = array_merge($params, $data); } $baseString = Oauth::buildBasestring($method, $url, $params); if ($signature->verify($baseString, $consumer->getConsumerSecret(), $consumer->getTokenSecret(), $params['oauth_signature']) !== false) { $this->callSuccess($response); $filterChain->handle($request, $response); } else { $this->callFailure($response); } } else { $this->callFailure($response); } } else { $this->callMissing($response); } } else { $this->callMissing($response); } }
/** * @expectedException \PSX\Http\Exception\BadRequestException */ public function testFailure() { $store = new Memory(); $handle = $this->makeHandshake($store); $username = '******'; $password = '******'; $nonce = $store->load('digest')->getNonce(); $opaque = $store->load('digest')->getOpaque(); $cnonce = md5(uniqid()); $nc = '00000001'; $ha1 = md5($username . ':psx:' . $password); $ha2 = md5('GET:/index.php'); $response = md5($ha1 . ':' . $nonce . ':' . $nc . ':' . $cnonce . ':auth:' . $ha2); $params = array('username' => $username, 'realm' => 'psx', 'nonce' => $nonce, 'qop' => 'auth', 'nc' => $nc, 'cnonce' => $cnonce, 'response' => $response, 'opaque' => $opaque); $request = new Request(new Url('http://localhost/index.php'), 'GET', array('Authorization' => 'Digest ' . Authentication::encodeParameters($params))); $response = new Response(); $filterChain = $this->getMockFilterChain(); $filterChain->expects($this->never())->method('handle'); $handle->handle($request, $response, $filterChain); }
public function handle(RequestInterface $request, ResponseInterface $response, FilterChainInterface $filterChain) { $authorization = $request->getHeader('Authorization'); if (!empty($authorization)) { $parts = explode(' ', $authorization, 2); $type = isset($parts[0]) ? $parts[0] : null; $data = isset($parts[1]) ? $parts[1] : null; if ($type == 'Digest' && !empty($data)) { $params = Authentication::decodeParameters($data); $algo = isset($params['algorithm']) ? $params['algorithm'] : 'MD5'; $qop = isset($params['qop']) ? $params['qop'] : 'auth'; if (!$this->digest instanceof Digest) { throw new BadRequestException('Digest not available'); } if ($this->digest->getOpaque() != $params['opaque']) { throw new BadRequestException('Invalid opaque'); } // build ha1 $ha1 = call_user_func_array($this->ha1Callback, array($params['username'])); if ($algo == 'MD5-sess') { $ha1 = md5($ha1 . ':' . $this->digest->getNonce() . ':' . $params['cnonce']); } // build ha2 if ($qop == 'auth-int') { $ha2 = md5($request->getMethod() . ':' . $request->getUri()->getPath() . ':' . md5($request->getBody())); } else { $ha2 = md5($request->getMethod() . ':' . $request->getUri()->getPath()); } // build response if ($qop == 'auth' || $qop == 'auth-int') { $hash = md5($ha1 . ':' . $this->digest->getNonce() . ':' . $params['nc'] . ':' . $params['cnonce'] . ':' . $qop . ':' . $ha2); } else { $hash = md5($ha1 . ':' . $this->digest->getNonce() . ':' . $ha2); } if (strcmp($hash, $params['response']) === 0) { $this->callSuccess($response, $hash); $filterChain->handle($request, $response); } else { $this->callFailure($response); } } else { $this->callMissing($response); } } else { $this->callMissing($response); } }
public function testFlow() { $testCase = $this; $http = new Http(new Callback(function (RequestInterface $request) use($testCase) { // request token if ($request->getUri()->getPath() == '/requestToken') { $auth = Authentication::decodeParameters((string) $request->getHeader('Authorization')); $testCase->assertEquals(self::CONSUMER_KEY, $auth['oauth_consumer_key']); $testCase->assertEquals('HMAC-SHA1', $auth['oauth_signature_method']); $testCase->assertTrue(isset($auth['oauth_timestamp'])); $testCase->assertTrue(isset($auth['oauth_nonce'])); $testCase->assertEquals('1.0', $auth['oauth_version']); $testCase->assertEquals('oob', $auth['oauth_callback']); $testCase->assertTrue(isset($auth['oauth_signature'])); $tmpToken = self::TMP_TOKEN; $tmpTokenSecret = self::TMP_TOKEN_SECRET; $response = <<<TEXT HTTP/1.1 200 OK Date: Thu, 26 Sep 2013 16:36:25 GMT Content-Type: application/x-www-form-urlencoded oauth_token={$tmpToken}&oauth_token_secret={$tmpTokenSecret}&oauth_callback_confirmed=1 TEXT; } elseif ($request->getUri()->getPath() == '/accessToken') { $auth = Authentication::decodeParameters((string) $request->getHeader('Authorization')); $testCase->assertEquals(self::CONSUMER_KEY, $auth['oauth_consumer_key']); $testCase->assertEquals(self::TMP_TOKEN, $auth['oauth_token']); $testCase->assertEquals('HMAC-SHA1', $auth['oauth_signature_method']); $testCase->assertTrue(isset($auth['oauth_timestamp'])); $testCase->assertTrue(isset($auth['oauth_nonce'])); $testCase->assertEquals('1.0', $auth['oauth_version']); $testCase->assertEquals(self::VERIFIER, $auth['oauth_verifier']); $testCase->assertTrue(isset($auth['oauth_signature'])); $token = self::TOKEN; $tokenSecret = self::TOKEN_SECRET; $response = <<<TEXT HTTP/1.1 200 OK Date: Thu, 26 Sep 2013 16:36:26 GMT Content-Type: application/x-www-form-urlencoded oauth_token={$token}&oauth_token_secret={$tokenSecret} TEXT; } elseif ($request->getUri()->getPath() == '/api') { $auth = Authentication::decodeParameters((string) $request->getHeader('Authorization')); $testCase->assertEquals(self::CONSUMER_KEY, $auth['oauth_consumer_key']); $testCase->assertEquals(self::TOKEN, $auth['oauth_token']); $testCase->assertEquals('HMAC-SHA1', $auth['oauth_signature_method']); $testCase->assertTrue(isset($auth['oauth_timestamp'])); $testCase->assertTrue(isset($auth['oauth_nonce'])); $testCase->assertEquals('1.0', $auth['oauth_version']); $testCase->assertTrue(isset($auth['oauth_signature'])); $response = <<<TEXT HTTP/1.1 200 OK Date: Thu, 26 Sep 2013 16:36:26 GMT Content-Type: text/html; charset=UTF-8 SUCCESS TEXT; } else { throw new \RuntimeException('Invalid path'); } return ResponseParser::convert($response, ResponseParser::MODE_LOOSE)->toString(); })); $oauth = new Oauth($http); // request token $url = new Url('http://127.0.0.1/requestToken'); $response = $oauth->requestToken($url, self::CONSUMER_KEY, self::CONSUMER_SECRET); $this->assertInstanceOf('PSX\\Oauth\\Provider\\Data\\Response', $response); $this->assertEquals(self::TMP_TOKEN, $response->getToken()); $this->assertEquals(self::TMP_TOKEN_SECRET, $response->getTokenSecret()); // if we have optained temporary credentials we can redirect the user // to grant access to the credentials // $oauth->userAuthorization($url, array('oauth_token' => $response->getToken())) // if the user gets redirected back we can exchange the temporary // credentials to an access token we also get an verifier as GET // parameter $url = new Url('http://127.0.0.1/accessToken'); $response = $oauth->accessToken($url, self::CONSUMER_KEY, self::CONSUMER_SECRET, self::TMP_TOKEN, self::TMP_TOKEN, self::VERIFIER); $this->assertInstanceOf('PSX\\Oauth\\Provider\\Data\\Response', $response); $this->assertEquals(self::TOKEN, $response->getToken()); $this->assertEquals(self::TOKEN_SECRET, $response->getTokenSecret()); // now we can make an request to the protected api $url = new Url('http://127.0.0.1/api'); $auth = $oauth->getAuthorizationHeader($url, self::CONSUMER_KEY, self::CONSUMER_SECRET, self::TOKEN, self::TOKEN_SECRET, 'HMAC-SHA1', 'GET'); $request = new GetRequest($url, array('Authorization' => $auth)); $response = $http->request($request); $this->assertEquals(200, $response->getStatusCode()); $this->assertEquals('SUCCESS', (string) $response->getBody()); }
protected function handleStatusCodeException(StatusCode\StatusCodeException $e, ResponseInterface $response) { $response->setStatus($e->getStatusCode()); if ($e instanceof StatusCode\MethodNotAllowedException) { $allowedMethods = $e->getAllowedMethods(); if (!empty($allowedMethods)) { $response->setHeader('Allow', implode(', ', $allowedMethods)); } } elseif ($e instanceof StatusCode\UnauthorizedException) { $type = $e->getType(); $parameters = $e->getParameters(); if (!empty($type)) { if (!empty($parameters)) { $response->setHeader('WWW-Authenticate', $type . ' ' . Authentication::encodeParameters($parameters)); } else { $response->setHeader('WWW-Authenticate', $type); } } } }