Reputation: 928
I created a test application to test if SSO (Single sign on) works. I use Auth0 as a SSO provider. Symfony 4.4 as application framework. I used this article from Auth0 to create the basics. So far I can login/logout.
When I login once (with credentials), logout after and then login again I am instandly logged in with the same account I used before. Without needing to fill in credentials again. It seems to remember the session or somehow does not completely logout a user. I want the user to have to login again with credentials after it logged out. Since some of my users will use one computer for the applications (so switching user is needed).
According to there docs/community I should look at this. But this seems to mean that I need API calls to add the ?federated
. Which the setup example does not use (probably the library does it for me). Also my logout function in the SecurityController that is generated by the make:auth
(or make:user
) doesn't execute the code anymore. Even if I change the function name it still logged me out. Only untill I remove/change the route name it stops. It's probably very bad but maybe if I had the chance to execute a API call when I logout I could do this API call.
The best thing I could imagine to do is change some settings in symfony or add some small piece of code to make it logout correclty. But I dont know how.
SecurityController.php
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends AbstractController
{
/**
* @Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
}
/**
* @Route("/logout", name="app_logout")
*/
public function logout()
{
// Does not trigger at all. It does not stop the page but just continues to redirect and logout.
dump($this->get('session'));
dump($session);
dump("test");
exit();
throw new \Exception('This method can be blank - it will be intercepted by the logout key on your firewall');
}
}
Auth0ResourceOwner.php
<?php
namespace App;
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\GenericOAuth2ResourceOwner;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
class Auth0ResourceOwner extends GenericOAuth2ResourceOwner
{
protected $paths = array(
'identifier' => 'user_id',
'nickname' => 'nickname',
'realname' => 'name',
'email' => 'email',
'profilepicture' => 'picture',
);
public function getAuthorizationUrl($redirectUri, array $extraParameters = array())
{
return parent::getAuthorizationUrl($redirectUri, array_merge(array(
'audience' => $this->options['audience'],
), $extraParameters));
}
protected function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults(array(
'authorization_url' => '{base_url}/authorize',
'access_token_url' => '{base_url}/oauth/token',
'infos_url' => '{base_url}/userinfo',
'audience' => '{base_url}/userinfo',
));
$resolver->setRequired(array(
'base_url',
));
$normalizer = function (Options $options, $value) {
return str_replace('{base_url}', $options['base_url'], $value);
};
$resolver->setNormalizer('authorization_url', $normalizer);
$resolver->setNormalizer('access_token_url', $normalizer);
$resolver->setNormalizer('infos_url', $normalizer);
$resolver->setNormalizer('audience', $normalizer);
}
}
routes.yaml
hwi_oauth_redirect:
resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
prefix: /connect
hwi_oauth_connect:
resource: "@HWIOAuthBundle/Resources/config/routing/connect.xml"
prefix: /connect
hwi_oauth_login:
resource: "@HWIOAuthBundle/Resources/config/routing/login.xml"
prefix: /login
auth0_login:
path: /auth0/callback
auth0_logout:
path: /auth0/logout
# controller: App/Controller/SecurityController::logout
hwi_oauth.yaml
hwi_oauth:
firewall_names: [main]
# https://github.com/hwi/HWIOAuthBundle/blob/master/Resources/doc/2-configuring_resource_owners.md
resource_owners:
auth0:
type: oauth2
class: 'App\Auth0ResourceOwner'
client_id: "%env(AUTH0_CLIENT_ID)%"
client_secret: "%env(AUTH0_CLIENT_SECRET)%"
base_url: "https://%env(AUTH0_DOMAIN)%"
scope: "openid profile email"
security.yaml
security:
encoders:
App\Entity\Users:
algorithm: auto
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\Users
property: username
oauth_hwi:
id: hwi_oauth.user.provider
# used to reload user from session & other features (e.g. switch_user)
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
provider: oauth_hwi
oauth:
resource_owners:
auth0: "/auth0/callback"
login_path: /login
failure_path: /login
default_target_path: /testPage
oauth_user_provider:
service: hwi_oauth.user.provider
guard:
authenticators:
- App\Security\LoginFormAuthenticator
logout:
path: /logout
# target: /login
access_control:
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
# Everyone that logged in can go to /
- { path: '^/testPage', roles: [IS_AUTHENTICATED_FULLY] }
.env
AUTH0_CLIENT_ID=not-so-secret-but-secret
AUTH0_CLIENT_SECRET=secret
AUTH0_DOMAIN=dev-...
Dump of user:
TestPageController.php on line 17:
HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUser {#3742 ▼
#username: "testUser"
}
I hope it's understandable. Any help is appreciated.
Upvotes: 3
Views: 1376
Reputation: 121
It looks like that you have to logout from the oauth service you are using, here is a similar issue.
src/Security/CustomLogoutSuccessHandler.php
<?php
namespace App\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
class CustomLogoutSuccessHandler implements LogoutSuccessHandlerInterface
{
private $target;
public function __construct(string $target)
{
$this->target = $target;
}
public function onLogoutSuccess(Request $request)
{
return new RedirectResponse($this->target);
}
}
security.yaml
logout:
path: /logout
success_handler: App\Security\CustomLogoutSuccessHandler
services.yaml
services:
App\Security\CustomLogoutSuccessHandler:
arguments: ['%env(resolve:LOGOUT_TARGET_URL)%']
.env
LOGOUT_TARGET_URL=https://{yourAuth0AppDomain}.auth0.com/v2/logout?returnTo={yourRedirectURL}&client_id={secret}
Using code from the Github issue redirects you 4 times. Logout->Route->(.env)Auth0->Route.
Using code shown above redirects you 3 times. Logout->Auth0->Route. Just a small improvement.
Upvotes: 3