Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit abc5d47

Browse filesBrowse files
Handle auth0 logout
1 parent d028339 commit abc5d47
Copy full SHA for abc5d47

File tree

5 files changed

+217
-0
lines changed
Filter options

5 files changed

+217
-0
lines changed

‎HappyrAuth0Bundle.php

Copy file name to clipboardExpand all lines: HappyrAuth0Bundle.php
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace Happyr\Auth0Bundle;
44

5+
use Happyr\Auth0Bundle\Security\Factory\Auth0LogoutFactory;
56
use Happyr\Auth0Bundle\Security\Factory\SSOFactory;
7+
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
68
use Symfony\Component\DependencyInjection\ContainerBuilder;
79
use Symfony\Component\HttpKernel\Bundle\Bundle;
810

@@ -13,8 +15,10 @@ public function build(ContainerBuilder $container)
1315
parent::build($container);
1416

1517
if ($container->hasExtension('security')) {
18+
/** @var SecurityExtension $extension */
1619
$extension = $container->getExtension('security');
1720
$extension->addSecurityListenerFactory(new SSOFactory());
21+
$extension->addSecurityListenerFactory(new Auth0LogoutFactory());
1822
}
1923
}
2024
}

‎Resources/config/security.yml

Copy file name to clipboardExpand all lines: Resources/config/security.yml
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,14 @@ services:
2323
- ~
2424
- ~
2525
abstract: true
26+
27+
happyr.auth0.security.authentication.provider.null:
28+
class: Happyr\Auth0Bundle\Security\Authentication\Provider\NullProvider
29+
public: false
30+
31+
happyr.auth0.security.authentication.listener.logout:
32+
class: Happyr\Auth0Bundle\Security\Firewall\Auth0LogoutListener
33+
parent: security.logout_listener
34+
abstract: true
35+
calls:
36+
- [ 'setAuth0Domain', ["%auth0.domain%"]]
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Happyr\Auth0Bundle\Security\Authentication\Provider;
5+
6+
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
7+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
8+
9+
final class NullProvider implements AuthenticationProviderInterface
10+
{
11+
public function authenticate(TokenInterface $token)
12+
{
13+
return $token;
14+
}
15+
16+
public function supports(TokenInterface $token)
17+
{
18+
return false;
19+
}
20+
21+
}
+140Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Happyr\Auth0Bundle\Security\Factory;
5+
6+
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;
7+
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
8+
use Symfony\Component\DependencyInjection\ChildDefinition;
9+
use Symfony\Component\DependencyInjection\ContainerBuilder;
10+
use Symfony\Component\DependencyInjection\Reference;
11+
12+
final class Auth0LogoutFactory implements SecurityFactoryInterface
13+
{
14+
/**
15+
* Configures the container services required to use the authentication listener.
16+
*
17+
* @param ContainerBuilder $container
18+
* @param string $id The unique id of the firewall
19+
* @param array $config The options array for the listener
20+
* @param string $userProvider The service id of the user provider
21+
* @param string $defaultEntryPoint
22+
*
23+
* @return array containing three values:
24+
* - the provider id
25+
* - the listener id
26+
* - the entry point id
27+
*/
28+
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
29+
{
30+
$listenerKeys[] = 'logout';
31+
$listenerId = 'happyr_auth0.security.logout_listener.'.$id;
32+
$listener = $container->setDefinition($listenerId, new ChildDefinition('happyr.auth0.security.authentication.listener.logout'));
33+
$listener->replaceArgument(3, array(
34+
'csrf_parameter' => $config['csrf_parameter'],
35+
'csrf_token_id' => $config['csrf_token_id'],
36+
'logout_path' => $config['path'],
37+
));
38+
$listeners[] = new Reference($listenerId);
39+
40+
// always use default success handler
41+
$logoutSuccessHandlerId = 'happyr_auth0.security.logout.success_handler.'.$id;
42+
$logoutSuccessHandler = $container->setDefinition($logoutSuccessHandlerId, new ChildDefinition('security.logout.success_handler'));
43+
$logoutSuccessHandler->replaceArgument(1, $config['target']);
44+
$listener->replaceArgument(2, new Reference($logoutSuccessHandlerId));
45+
46+
// add CSRF provider
47+
if (isset($config['csrf_token_generator'])) {
48+
$listener->addArgument(new Reference($config['csrf_token_generator']));
49+
}
50+
51+
// add session logout handler
52+
if (true === $config['invalidate_session']) {
53+
$listener->addMethodCall('addHandler', array(new Reference('security.logout.handler.session')));
54+
}
55+
56+
// add cookie logout handler
57+
if (count($config['delete_cookies']) > 0) {
58+
$cookieHandlerId = 'happyr_auth0.security.logout.handler.cookie_clearing.'.$id;
59+
$cookieHandler = $container->setDefinition($cookieHandlerId, new ChildDefinition('security.logout.handler.cookie_clearing'));
60+
$cookieHandler->addArgument($config['delete_cookies']);
61+
62+
$listener->addMethodCall('addHandler', array(new Reference($cookieHandlerId)));
63+
}
64+
65+
// add custom handlers
66+
foreach ($config['handlers'] as $handlerId) {
67+
$listener->addMethodCall('addHandler', array(new Reference($handlerId)));
68+
}
69+
70+
// register with LogoutUrlGenerator
71+
$container
72+
->getDefinition('security.logout_url_generator')
73+
->addMethodCall('registerListener', array(
74+
$id,
75+
$config['path'],
76+
$config['csrf_token_id'],
77+
$config['csrf_parameter'],
78+
isset($config['csrf_token_generator']) ? new Reference($config['csrf_token_generator']) : null,
79+
null, // This is wrong in Symfony 4.0. We should be able to detect and pass the firewall context somehow.
80+
))
81+
;
82+
83+
84+
return [
85+
'happyr.auth0.security.authentication.provider.null',
86+
$listenerId,
87+
$defaultEntryPoint
88+
];
89+
}
90+
91+
public function addConfiguration(NodeDefinition $builder)
92+
{
93+
$builder
94+
->treatTrueLike(array())
95+
->canBeUnset()
96+
->children()
97+
->scalarNode('csrf_parameter')->defaultValue('_csrf_token')->end()
98+
->scalarNode('csrf_token_generator')->cannotBeEmpty()->end()
99+
->scalarNode('csrf_token_id')->defaultValue('logout')->end()
100+
->scalarNode('path')->defaultValue('/logout')->end()
101+
->scalarNode('target')->defaultValue('/')->end()
102+
->scalarNode('success_handler')->end()
103+
->booleanNode('invalidate_session')->defaultTrue()->end()
104+
->end()
105+
->fixXmlConfig('delete_cookie')
106+
->children()
107+
->arrayNode('delete_cookies')
108+
->beforeNormalization()
109+
->ifTrue(function ($v) { return is_array($v) && is_int(key($v)); })
110+
->then(function ($v) { return array_map(function ($v) { return array('name' => $v); }, $v); })
111+
->end()
112+
->useAttributeAsKey('name')
113+
->prototype('array')
114+
->children()
115+
->scalarNode('path')->defaultNull()->end()
116+
->scalarNode('domain')->defaultNull()->end()
117+
->end()
118+
->end()
119+
->end()
120+
->end()
121+
->fixXmlConfig('handler')
122+
->children()
123+
->arrayNode('handlers')
124+
->prototype('scalar')->end()
125+
->end()
126+
->end()
127+
;
128+
}
129+
130+
public function getPosition()
131+
{
132+
return 'remember_me';
133+
}
134+
135+
public function getKey()
136+
{
137+
return 'auth0_logout';
138+
}
139+
140+
}
+41Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Happyr\Auth0Bundle\Security\Firewall;
5+
6+
use Symfony\Component\HttpFoundation\RedirectResponse;
7+
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
8+
use Symfony\Component\Security\Http\Firewall\LogoutListener;
9+
10+
final class Auth0LogoutListener extends LogoutListener
11+
{
12+
/** @var string */
13+
private $auth0Domain;
14+
15+
public function setAuth0Domain(string $auth0Domain)
16+
{
17+
$this->auth0Domain = $auth0Domain;
18+
}
19+
20+
public function handle(GetResponseEvent $event)
21+
{
22+
parent::handle($event);
23+
24+
if ($event->hasResponse()) {
25+
$request = $event->getRequest();
26+
$response = $event->getResponse();
27+
if (!$response instanceof RedirectResponse) {
28+
throw new \UnexpectedValueException("Auth0 Logout listener expects response to be a RedirectResponse. Perhaps the bundle is incompatible with your Symfony version?");
29+
}
30+
31+
$targetUrl = $response->getTargetUrl();
32+
if (0 !== strpos($targetUrl, 'http')) {
33+
$targetUrl = $request->getUriForPath($targetUrl);
34+
}
35+
36+
$auth0LogoutUrl = sprintf("https://%s/v2/logout?returnTo=%s", $this->auth0Domain, urlencode($targetUrl));
37+
38+
$response->setTargetUrl($auth0LogoutUrl);
39+
}
40+
}
41+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.