Make content type check more robust

Refactoring:
* Moved discovery request test to a base class.
* added unit test for this corner case.

Change-Id: I16b38b7cced97b419b3d5b8e65ae62df803ae3fb
This commit is contained in:
Sebastian Marcet 2015-03-23 11:49:58 -03:00
parent 7970a10544
commit 7b22f060fb
13 changed files with 150 additions and 49 deletions

View File

@ -1,27 +0,0 @@
<?php
use openid\XRDS\XRDSDocumentBuilder;
class HomeController extends BaseController
{
private $discovery;
public function __construct(DiscoveryController $discovery)
{
$this->discovery = $discovery;
}
public function index()
{
//This field contains a semicolon-separated list of representation schemes
//which will be accepted in the response to this request.
$accept = Request::header('Accept');
if (strstr($accept, XRDSDocumentBuilder::ContentType))
return $this->discovery->idp();
if (Auth::guest())
return View::make("home");
else {
return Redirect::action("UserController@getProfile");
}
}
}

View File

@ -5,7 +5,7 @@ use openid\services\IServerConfigurationService;
use openid\XRDS\XRDSDocumentBuilder;
use utils\services\IAuthService;
class DiscoveryController extends BaseController
class DiscoveryController extends OpenIdController
{
private $openid_protocol;
@ -25,12 +25,10 @@ class DiscoveryController extends BaseController
*/
public function idp()
{
//This field contains a semicolon-separated list of representation schemes
//which will be accepted in the response to this request.
$accept = Request::header('Accept');
if (strstr($accept, XRDSDocumentBuilder::ContentType)) {
if ($this->isDiscoveryRequest()) {
$response = Response::make($this->openid_protocol->getXRDSDiscovery(IOpenIdProtocol::OpenIdXRDSModeIdp), 200);
$response->header('Content-Type', "application/xrds+xml; charset=UTF-8");
$this->setDiscoveryResponseType($response);
} else {
$response = View::make("home");
}
@ -51,13 +49,11 @@ class DiscoveryController extends BaseController
$user = $this->auth_service->getUserByOpenId($identifier);
if (is_null($user))
return View::make("404");
//This field contains a semicolon-separated list of representation schemes
//which will be accepted in the response to this request.
$accept = Request::header('Accept');
$local_identifier = $this->server_config_service->getUserIdentityEndpointURL($identifier);
if (strstr($accept, XRDSDocumentBuilder::ContentType)) {
if ($this->isDiscoveryRequest()) {
$response = Response::make($this->openid_protocol->getXRDSDiscovery(IOpenIdProtocol::OpenIdXRDSModeUser, $local_identifier), 200);
$response->header('Content-Type', "application/xrds+xml; charset=UTF-8");
$this->setDiscoveryResponseType($response);
} else {
$response = View::make("identity");
}

View File

@ -0,0 +1,26 @@
<?php
/**
* Class HomeController
*/
class HomeController extends OpenIdController
{
private $discovery;
public function __construct(DiscoveryController $discovery)
{
$this->discovery = $discovery;
}
public function index()
{
if ($this->isDiscoveryRequest())
return $this->discovery->idp();
if (Auth::guest())
return View::make("home");
else
return Redirect::action("UserController@getProfile");
}
}

View File

@ -0,0 +1,37 @@
<?php
/**
* Copyright 2015 Openstack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use openid\XRDS\XRDSDocumentBuilder;
/**
* Class OpenIdController
*/
abstract class OpenIdController extends BaseController {
/**
* @return bool
*/
protected function isDiscoveryRequest(){
//This field contains a semicolon-separated list of representation schemes
//which will be accepted in the response to this request.
$accept = Request::header('Accept');
return strstr($accept, XRDSDocumentBuilder::ContentType) !== false;
}
/**
* @param $response
*/
protected function setDiscoveryResponseType($response){
$response->header('Content-Type', implode('; ', array(XRDSDocumentBuilder::ContentType, XRDSDocumentBuilder::Charset)));
}
}

View File

@ -6,6 +6,9 @@ use openid\IOpenIdProtocol;
use openid\services\IMementoOpenIdRequestService;
use openid\strategies\OpenIdResponseStrategyFactoryMethod;
/**
* Class OpenIdProviderController
*/
class OpenIdProviderController extends BaseController
{
private $openid_protocol;

View File

@ -21,7 +21,10 @@ use strategies\OAuth2LoginStrategy;
use utils\services\IAuthService;
use utils\services\IServerConfigurationService as IUtilsServerConfigurationService;
class UserController extends BaseController
/**
* Class UserController
*/
class UserController extends OpenIdController
{
private $openid_memento_service;
@ -175,10 +178,8 @@ class UserController extends BaseController
$user = $this->auth_service->getUserByOpenId($identifier);
if (is_null($user))
return View::make("404");
//This field contains a semicolon-separated list of representation schemes
//which will be accepted in the response to this request.
$accept = Request::header('Accept');
if (strstr($accept, XRDSDocumentBuilder::ContentType)) {
if ($this->isDiscoveryRequest()) {
/*
* If the Claimed Identifier was not previously discovered by the Relying Party
* (the "openid.identity" in the request was "http://specs.openid.net/auth/2.0/identifier_select"

View File

@ -13,8 +13,9 @@ class InsertMarketplaceApiEndpointsScopes extends Migration {
public function up()
{
$resource_server = ResourceServer::first();
$resource_server = ResourceServer::first();
if(!$resource_server) return;
// public clouds
Api::create(
array(

View File

@ -9,8 +9,9 @@ namespace openid\XRDS;
final class XRDSDocumentBuilder
{
const ContentType = 'application/xrds+xml';
const XRDNamespace = 'xri://$xrd*($v*2.0)';
const ContentType = 'application/xrds+xml';
const Charset = 'charset=UTF-8';
const XRDNamespace = 'xri://$xrd*($v*2.0)';
const XRDSNamespace = 'xri://$xrds';
private $elements;

View File

@ -19,7 +19,7 @@ use utils\services\IAuthService;
/**
* Class OAuth2ProtectedApiTest
*/
abstract class OAuth2ProtectedApiTest extends TestCase {
abstract class OAuth2ProtectedApiTest extends OpenStackIDBaseTest {
protected $access_token;
protected $client_id;

View File

@ -8,7 +8,7 @@ use utils\services\IAuthService;
* Class OAuth2ProtocolTest
* Test Suite for OAuth2 Protocol
*/
class OAuth2ProtocolTest extends TestCase
class OAuth2ProtocolTest extends OpenStackIDBaseTest
{
private $current_realm;

View File

@ -14,7 +14,7 @@ use Zend\Crypt\PublicKey\DiffieHellman;
* Class OpenIdProtocolTest
* Test Suite for OpenId Protocol
*/
class OpenIdProtocolTest extends TestCase
class OpenIdProtocolTest extends OpenStackIDBaseTest
{
private $current_realm;
private $g;
@ -755,4 +755,22 @@ class OpenIdProtocolTest extends TestCase
$content = $response->getContent();
}
public function testDiscovery(){
$response = $this->action("GET", "HomeController@index",
array(),
array(),
array(),
// Symfony interally prefixes headers with "HTTP", so
array('HTTP_Accept' => 'text/html; q=0.3, application/xhtml+xml; q=0.5, application/xrds+xml'));
$this->assertResponseStatus(200);
// I just needed to access the public
// headers var (which is a Symfony ResponseHeaderBag object)
$this->assertEquals('application/xrds+xml; charset=UTF-8', $response->headers->get('Content-Type'));
$content = $response->getContent();
$this->assertTrue(strpos($content,'<xrds:XRDS')!==false);
$this->assertTrue(strpos($content,'http://specs.openid.net/auth/2.0/server')!==false);
}
}

View File

@ -0,0 +1,45 @@
<?php
/**
* Copyright 2015 Openstack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class OpenStackIDBaseTest
*/
abstract class OpenStackIDBaseTest extends TestCase {
protected function prepareForTests()
{
DB::table('banned_ips')->delete();
DB::table('user_exceptions_trail')->delete();
DB::table('server_configuration')->delete();
DB::table('server_extensions')->delete();
DB::table('oauth2_client_api_scope')->delete();
DB::table('oauth2_client_authorized_uri')->delete();
DB::table('oauth2_access_token')->delete();
DB::table('oauth2_refresh_token')->delete();
DB::table('oauth2_client')->delete();
DB::table('openid_trusted_sites')->delete();
DB::table('openid_associations')->delete();
DB::table('openid_users')->delete();
DB::table('oauth2_api_endpoint_api_scope')->delete();
DB::table('oauth2_api_endpoint')->delete();
DB::table('oauth2_api_scope')->delete();
DB::table('oauth2_api')->delete();
DB::table('oauth2_resource_server')->delete();
parent::prepareForTests();
}
}