Skip to content

Commit

Permalink
Merge pull request formapro#11 from formapro/trust-root-from-request
Browse files Browse the repository at this point in the history
Trust root from request
  • Loading branch information
makasim committed Nov 22, 2011
2 parents 4f3ab8f + 3b4d9e6 commit e0bb24d
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 47 deletions.
25 changes: 25 additions & 0 deletions Bridge/Consumer/LightOpenIdConsumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ public function __construct(array $parameters = array(), $lightOpenIDClass = 'Li
), $parameters);
}

/**
* {@inheritdoc}
*/
public function changeTrustRoot($trustRoot)
{
$this->parameters['trust_root'] = $trustRoot;
$this->lightOpenID = null;
}

/**
* {@inheritdoc}
*/
public function authenticateUrl($identifier, $returnUrl)
{
$lightOpenId = $this->getLightOpenID();
Expand All @@ -40,6 +52,9 @@ public function authenticateUrl($identifier, $returnUrl)
return $lightOpenId->authUrl();
}

/**
* {@inheritdoc}
*/
public function complete(array $response, $returnUrl)
{
$lightOpenId = $this->getLightOpenID();
Expand All @@ -65,4 +80,14 @@ protected function getLightOpenID()

return $this->lightOpenID;
}

/**
* {@inheritdoc}
*/
public function supports($identifier)
{
// should support any kind of openid providers
// can be used as default
return true;
}
}
20 changes: 20 additions & 0 deletions Consumer/ConsumerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@

interface ConsumerInterface
{
/**
* This method allows change trustRoot in runtime.
*
* @abstract
*
* @param string $trustRoot
*
* @return void
*/
public function changeTrustRoot($trustRoot);

/**
* @abstract
*
Expand All @@ -24,4 +35,13 @@ public function authenticateUrl($identifier, $returnUrl);
* @return array
*/
public function complete(array $response, $returnUrl);

/**
* @abstract
*
* @param string $identifier
*
* @return boolean
*/
public function supports($identifier);
}
41 changes: 41 additions & 0 deletions Consumer/ConsumerProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
namespace Fp\OpenIdBundle\Consumer;

class ConsumerProvider
{
protected $consumers = array();

protected $defaultConsumer;

public function addConsumer(ConsumerInterface $consumer)
{
$this->consumers[] = $consumer;
}

public function setDefault(ConsumerInterface $consumer)
{
$this->defaultConsumer = $consumer;
}

/**
* @throws \InvalidArgumentException
*
* @param string $identifier
*
* @return \Fp\OpenIdBundle\Consumer\ConsumerInterface
*/
public function provide($identifier)
{
foreach ($this->consumers as $consumer) {
if ($consumer->supports($identifier)) {
return $consumer;
}
}

if ($this->defaultConsumer && $this->defaultConsumer->supports($identifier)) {
return $this->defaultConsumer;
}

throw new \InvalidArgumentException(sprintf('Cannot provide consumer for the identifier: %s', $identifier));
}
}
34 changes: 15 additions & 19 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,24 @@ public function getConfigTreeBuilder()
->end()
->end()
->arrayNode('consumers')
->cannotBeEmpty()
->isRequired()
->children()
->arrayNode('light_open_id')
->children()
->arrayNode('required')
->addDefaultsIfNotSet()
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->arrayNode('optional')
->addDefaultsIfNotSet()
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->scalarNode('trust_root')->cannotBeEmpty()->end()
->requiresAtLeastOneElement()
->useAttributeAsKey('name')
->prototype('array')
->children()
->arrayNode('required')
->addDefaultsIfNotSet()
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->arrayNode('optional')
->addDefaultsIfNotSet()
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->scalarNode('trust_root')->defaultValue('from_request')->cannotBeEmpty()->end()
->scalarNode('default')->defaultFalse()->end()
->end()
->end()
// ->children()
//
// ->end()
->end()
->end()
;
Expand Down
45 changes: 43 additions & 2 deletions DependencyInjection/FpOpenIdExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Reference;

class FpOpenIdExtension extends Extension
{
Expand All @@ -22,9 +23,49 @@ public function load(array $configs, ContainerBuilder $container)
$container->setParameter('fp_openid.security.authentication.provider.parameters', $configs['provider']);

foreach ($configs['consumers'] as $name => $parameters) {
$container->setParameter("fp_openid.consumer.{$name}.parameters", $parameters);
}
// if only one consumer configured use it as default.
if (1 == count($configs['consumers'])) {
$configs['consumers']['default'] = true;
}

// try to guess a consumer service key
if ($container->hasDefinition($name)) {
$serviceKey = $name;
} else if ($container->hasDefinition("fp_openid.consumer.{$name}")) {
$serviceKey = "fp_openid.consumer.{$name}";
} else {
throw new \InvalidArgumentException(sprintf(
'Cannot find a consumer service definition for a given configuration option %s, tried next services: %s, %s',
$name,
$name,
"fp_openid.consumer.{$name}"
));
}

$consumerDefinition = $container->getDefinition($serviceKey);
$consumerArguments = $consumerDefinition->getArguments();
$consumerArguments[0] = $parameters;
$consumerDefinition->setArguments($consumerArguments);

// dynamically set trust root from a request
if ('from_request' == $parameters['trust_root']) {
$trustRootListenerDefinition = $container->getDefinition('fp_openid.trust_root_listener');
$trustRootListenerDefinition->addMethodCall('addConsumer', array(new Reference($serviceKey)));
}

// add consumers to provider
$consumerProviderDefinition = $container->getDefinition('fp_openid.consumer.provider');
if ($parameters['default']) {
$consumerProviderDefinition->addMethodCall(
'setDefault',
array(new Reference($serviceKey))
);
} else {
$consumerProviderDefinition->addMethodCall(
'addConsumer',
array(new Reference($serviceKey))
);
}
}
}
}
42 changes: 42 additions & 0 deletions Event/AuthenticationEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
namespace Fp\OpenIdBundle\Event;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\Event;

use Fp\OpenIdBundle\Security\Core\Authentication\Token\OpenIdToken;

class AuthenticationEvent extends Event
{
/**
* @var Request
*/
protected $request;

/**
* @var OpenIdToken
*/
protected $token;

public function __construct(Request $request, OpenIdToken $token)
{
$this->token = $token;
$this->request = $request;
}

/**
* @return \Fp\OpenIdBundle\Security\Core\Authentication\Token\OpenIdToken
*/
public function getToken()
{
return $this->token;
}

/**
* @return \Symfony\Component\HttpFoundation\Request
*/
public function getRequest()
{
return $this->request;
}
}
46 changes: 46 additions & 0 deletions EventListener/TrustRootListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
namespace Fp\OpenIdBundle\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;

use Fp\OpenIdBundle\Event\AuthenticationEvent;
use Fp\OpenIdBundle\Consumer\ConsumerInterface;

class TrustRootListener implements EventSubscriberInterface
{
/**
* @var array
*/
protected $consumers = array();

/**
* @param \Fp\OpenIdBundle\Consumer\ConsumerInterface $consumer
*
* @return void
*/
public function addConsumer(ConsumerInterface $consumer)
{
$this->consumers[] = $consumer;
}

/**
* @param \Fp\OpenIdBundle\Event\AuthenticationEvent $event
*
* @return void
*/
public function onOpenidBeforeAuthentication(AuthenticationEvent $event)
{
$request = $event->getRequest();
foreach ($this->consumers as $consumer) {
$consumer->changeTrustRoot($request->getHttpHost());
}
}

/**
* {@inheritdoc}
*/
static function getSubscribedEvents()
{
return array('fp_openid.before_authentication' => 'onOpenidBeforeAuthentication');
}
}
17 changes: 13 additions & 4 deletions Resources/config/openid.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@
<parameter key="fp_openid.security.authentication.token_persister.class">Fp\OpenIdBundle\Security\Core\Authentication\Token\TokenPersister</parameter>
<parameter key="fp_openid.security.authentication.token_persister.sessionKey">_fp_openid.security.authentication.token_persister.openid</parameter>

<parameter key="fp_openid.consumer.provider.class">Fp\OpenIdBundle\Consumer\ConsumerProvider</parameter>

<parameter key="fp_openid.consumer.light_open_id.class">Fp\OpenIdBundle\Bridge\Consumer\LightOpenIdConsumer</parameter>
<parameter key="fp_openid.consumer.light_open_id.parameters"></parameter>

<parameter key="openid.view.simple_form">FpOpenIdBundle:OpenId:simple_form.html.twig</parameter>

<parameter key="fp_openid.trust_root_listener.class">Fp\OpenIdBundle\EventListener\TrustRootListener</parameter>
</parameters>

<services>

<service id="security.authentication.provider.openid" class="%fp_openid.security.authentication.provider.class%" >
<argument type="service" id="fp_openid.consumer" />
<argument type="service" id="fp_openid.consumer.provider" />
<argument type="service" id="router" />
<argument type="service" id="fp_openid.security.authentication.token_persister" />
<argument>%fp_openid.security.authentication.provider.parameters%</argument>
Expand All @@ -35,16 +38,22 @@
abstract="true">
</service>

<service id="fp_openid.consumer" alias="fp_openid.consumer.light_open_id">
<service id="fp_openid.consumer.provider" class="%fp_openid.consumer.provider.class%">
</service>

<service id="fp_openid.consumer.light_open_id" class="%fp_openid.consumer.light_open_id.class%">
<argument>%fp_openid.consumer.light_open_id.parameters%</argument>
<argument type="collection"></argument>
</service>

<service id="fp_openid.security.authentication.token_persister" class="%fp_openid.security.authentication.token_persister.class%" >
<argument>%fp_openid.security.authentication.token_persister.sessionKey%</argument>
<argument type="service" id="session" />
</service>

<service id="fp_openid.trust_root_listener" class="%fp_openid.trust_root_listener.class%">
<!-- <tag name="kernel.event_subscriber"></tag> -->
<tag name="kernel.event_listener" event="fp_openid.before_authentication" method="onOpenidBeforeAuthentication"/>
</service>

</services>
</container>
Loading

0 comments on commit e0bb24d

Please sign in to comment.